diff --git a/localcdn/altui/popper.js b/localcdn/altui/popper.js
index de1de74..acb1d81 100644
--- a/localcdn/altui/popper.js
+++ b/localcdn/altui/popper.js
@@ -1,1850 +1,2624 @@
-/**
- * @popperjs/core v2.4.4 - MIT License
+/**!
+ * @fileOverview Kickass library to create and place poppers near their reference elements.
+ * @version 1.16.1
+ * @license
+ * Copyright (c) 2016 Federico Zivolo and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
*/
-
(function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (global = global || self, factory(global.Popper = {}));
-}(this, (function (exports) { 'use strict';
-
- function getBoundingClientRect(element) {
- var rect = element.getBoundingClientRect();
- return {
- width: rect.width,
- height: rect.height,
- top: rect.top,
- right: rect.right,
- bottom: rect.bottom,
- left: rect.left,
- x: rect.left,
- y: rect.top
- };
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.Popper = factory());
+}(this, (function () { 'use strict';
+
+var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined';
+
+var timeoutDuration = function () {
+ var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
+ for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
+ if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
+ return 1;
+ }
}
+ return 0;
+}();
- /*:: import type { Window } from '../types'; */
-
- /*:: declare function getWindow(node: Node | Window): Window; */
- function getWindow(node) {
- if (node.toString() !== '[object Window]') {
- var ownerDocument = node.ownerDocument;
- return ownerDocument ? ownerDocument.defaultView : window;
+function microtaskDebounce(fn) {
+ var called = false;
+ return function () {
+ if (called) {
+ return;
+ }
+ called = true;
+ window.Promise.resolve().then(function () {
+ called = false;
+ fn();
+ });
+ };
+}
+
+function taskDebounce(fn) {
+ var scheduled = false;
+ return function () {
+ if (!scheduled) {
+ scheduled = true;
+ setTimeout(function () {
+ scheduled = false;
+ fn();
+ }, timeoutDuration);
}
+ };
+}
+
+var supportsMicroTasks = isBrowser && window.Promise;
- return node;
+/**
+* Create a debounced version of a method, that's asynchronously deferred
+* but called in the minimum time possible.
+*
+* @method
+* @memberof Popper.Utils
+* @argument {Function} fn
+* @returns {Function}
+*/
+var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
+
+/**
+ * Check if the given variable is a function
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Any} functionToCheck - variable to check
+ * @returns {Boolean} answer to: is a function?
+ */
+function isFunction(functionToCheck) {
+ var getType = {};
+ return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
+}
+
+/**
+ * Get CSS computed property of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Eement} element
+ * @argument {String} property
+ */
+function getStyleComputedProperty(element, property) {
+ if (element.nodeType !== 1) {
+ return [];
}
+ // NOTE: 1 DOM access here
+ var window = element.ownerDocument.defaultView;
+ var css = window.getComputedStyle(element, null);
+ return property ? css[property] : css;
+}
- function getWindowScroll(node) {
- var win = getWindow(node);
- var scrollLeft = win.pageXOffset;
- var scrollTop = win.pageYOffset;
- return {
- scrollLeft: scrollLeft,
- scrollTop: scrollTop
- };
+/**
+ * Returns the parentNode or the host of the element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} parent
+ */
+function getParentNode(element) {
+ if (element.nodeName === 'HTML') {
+ return element;
}
+ return element.parentNode || element.host;
+}
- /*:: declare function isElement(node: mixed): boolean %checks(node instanceof
- Element); */
+/**
+ * Returns the scrolling parent of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} scroll parent
+ */
+function getScrollParent(element) {
+ // Return body, `getScroll` will take care to get the correct `scrollTop` from it
+ if (!element) {
+ return document.body;
+ }
- function isElement(node) {
- var OwnElement = getWindow(node).Element;
- return node instanceof OwnElement || node instanceof Element;
+ switch (element.nodeName) {
+ case 'HTML':
+ case 'BODY':
+ return element.ownerDocument.body;
+ case '#document':
+ return element.body;
}
- /*:: declare function isHTMLElement(node: mixed): boolean %checks(node instanceof
- HTMLElement); */
+ // Firefox want us to check `-x` and `-y` variations as well
- function isHTMLElement(node) {
- var OwnElement = getWindow(node).HTMLElement;
- return node instanceof OwnElement || node instanceof HTMLElement;
- }
+ var _getStyleComputedProp = getStyleComputedProperty(element),
+ overflow = _getStyleComputedProp.overflow,
+ overflowX = _getStyleComputedProp.overflowX,
+ overflowY = _getStyleComputedProp.overflowY;
- function getHTMLElementScroll(element) {
- return {
- scrollLeft: element.scrollLeft,
- scrollTop: element.scrollTop
- };
+ if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
+ return element;
}
- function getNodeScroll(node) {
- if (node === getWindow(node) || !isHTMLElement(node)) {
- return getWindowScroll(node);
- } else {
- return getHTMLElementScroll(node);
- }
+ return getScrollParent(getParentNode(element));
+}
+
+/**
+ * Returns the reference node of the reference object, or the reference object itself.
+ * @method
+ * @memberof Popper.Utils
+ * @param {Element|Object} reference - the reference element (the popper will be relative to this)
+ * @returns {Element} parent
+ */
+function getReferenceNode(reference) {
+ return reference && reference.referenceNode ? reference.referenceNode : reference;
+}
+
+var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
+var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
+
+/**
+ * Determines if the browser is Internet Explorer
+ * @method
+ * @memberof Popper.Utils
+ * @param {Number} version to check
+ * @returns {Boolean} isIE
+ */
+function isIE(version) {
+ if (version === 11) {
+ return isIE11;
+ }
+ if (version === 10) {
+ return isIE10;
}
+ return isIE11 || isIE10;
+}
- function getNodeName(element) {
- return element ? (element.nodeName || '').toLowerCase() : null;
+/**
+ * Returns the offset parent of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} offset parent
+ */
+function getOffsetParent(element) {
+ if (!element) {
+ return document.documentElement;
}
- function getDocumentElement(element) {
- // $FlowFixMe: assume body is always available
- return (isElement(element) ? element.ownerDocument : element.document).documentElement;
+ var noOffsetParent = isIE(10) ? document.body : null;
+
+ // NOTE: 1 DOM access here
+ var offsetParent = element.offsetParent || null;
+ // Skip hidden elements which don't have an offsetParent
+ while (offsetParent === noOffsetParent && element.nextElementSibling) {
+ offsetParent = (element = element.nextElementSibling).offsetParent;
}
- function getWindowScrollBarX(element) {
- // If has a CSS width greater than the viewport, then this will be
- // incorrect for RTL.
- // Popper 1 is broken in this case and never had a bug report so let's assume
- // it's not an issue. I don't think anyone ever specifies width on
- // anyway.
- // Browsers where the left scrollbar doesn't cause an issue report `0` for
- // this (e.g. Edge 2019, IE11, Safari)
- return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
+ var nodeName = offsetParent && offsetParent.nodeName;
+
+ if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
+ return element ? element.ownerDocument.documentElement : document.documentElement;
}
- function getComputedStyle(element) {
- return getWindow(element).getComputedStyle(element);
+ // .offsetParent will return the closest TH, TD or TABLE in case
+ // no offsetParent is present, I hate this job...
+ if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
+ return getOffsetParent(offsetParent);
}
- function isScrollParent(element) {
- // Firefox wants us to check `-x` and `-y` variations as well
- var _getComputedStyle = getComputedStyle(element),
- overflow = _getComputedStyle.overflow,
- overflowX = _getComputedStyle.overflowX,
- overflowY = _getComputedStyle.overflowY;
+ return offsetParent;
+}
- return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
+function isOffsetContainer(element) {
+ var nodeName = element.nodeName;
+
+ if (nodeName === 'BODY') {
+ return false;
}
+ return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
+}
- // Composite means it takes into account transforms as well as layout.
+/**
+ * Finds the root node (document, shadowDOM root) of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} node
+ * @returns {Element} root node
+ */
+function getRoot(node) {
+ if (node.parentNode !== null) {
+ return getRoot(node.parentNode);
+ }
- function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
- if (isFixed === void 0) {
- isFixed = false;
- }
+ return node;
+}
- var documentElement = getDocumentElement(offsetParent);
- var rect = getBoundingClientRect(elementOrVirtualElement);
- var isOffsetParentAnElement = isHTMLElement(offsetParent);
- var scroll = {
- scrollLeft: 0,
- scrollTop: 0
- };
- var offsets = {
- x: 0,
- y: 0
- };
+/**
+ * Finds the offset parent common to the two provided nodes
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element1
+ * @argument {Element} element2
+ * @returns {Element} common offset parent
+ */
+function findCommonOffsetParent(element1, element2) {
+ // This check is needed to avoid errors in case one of the elements isn't defined for any reason
+ if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
+ return document.documentElement;
+ }
- if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
- if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
- isScrollParent(documentElement)) {
- scroll = getNodeScroll(offsetParent);
- }
+ // Here we make sure to give as "start" the element that comes first in the DOM
+ var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
+ var start = order ? element1 : element2;
+ var end = order ? element2 : element1;
- if (isHTMLElement(offsetParent)) {
- offsets = getBoundingClientRect(offsetParent);
- offsets.x += offsetParent.clientLeft;
- offsets.y += offsetParent.clientTop;
- } else if (documentElement) {
- offsets.x = getWindowScrollBarX(documentElement);
- }
+ // Get common ancestor container
+ var range = document.createRange();
+ range.setStart(start, 0);
+ range.setEnd(end, 0);
+ var commonAncestorContainer = range.commonAncestorContainer;
+
+ // Both nodes are inside #document
+
+ if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
+ if (isOffsetContainer(commonAncestorContainer)) {
+ return commonAncestorContainer;
}
- return {
- x: rect.left + scroll.scrollLeft - offsets.x,
- y: rect.top + scroll.scrollTop - offsets.y,
- width: rect.width,
- height: rect.height
- };
+ return getOffsetParent(commonAncestorContainer);
}
- // Returns the layout rect of an element relative to its offsetParent. Layout
- // means it doesn't take into account transforms.
- function getLayoutRect(element) {
- return {
- x: element.offsetLeft,
- y: element.offsetTop,
- width: element.offsetWidth,
- height: element.offsetHeight
- };
+ // one of the nodes is inside shadowDOM, find which one
+ var element1root = getRoot(element1);
+ if (element1root.host) {
+ return findCommonOffsetParent(element1root.host, element2);
+ } else {
+ return findCommonOffsetParent(element1, getRoot(element2).host);
}
+}
- function getParentNode(element) {
- if (getNodeName(element) === 'html') {
- return element;
- }
+/**
+ * Gets the scroll value of the given element in the given side (top and left)
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @argument {String} side `top` or `left`
+ * @returns {number} amount of scrolled pixels
+ */
+function getScroll(element) {
+ var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
- return (// $FlowFixMe: this is a quicker (but less type safe) way to save quite some bytes from the bundle
- element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
- element.parentNode || // DOM Element detected
- // $FlowFixMe: need a better way to handle this...
- element.host || // ShadowRoot detected
- // $FlowFixMe: HTMLElement is a Node
- getDocumentElement(element) // fallback
+ var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
+ var nodeName = element.nodeName;
- );
+ if (nodeName === 'BODY' || nodeName === 'HTML') {
+ var html = element.ownerDocument.documentElement;
+ var scrollingElement = element.ownerDocument.scrollingElement || html;
+ return scrollingElement[upperSide];
}
- function getScrollParent(node) {
- if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
- // $FlowFixMe: assume body is always available
- return node.ownerDocument.body;
- }
+ return element[upperSide];
+}
+
+/*
+ * Sum or subtract the element scroll values (left and top) from a given rect object
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} rect - Rect object you want to change
+ * @param {HTMLElement} element - The element from the function reads the scroll values
+ * @param {Boolean} subtract - set to true if you want to subtract the scroll values
+ * @return {Object} rect - The modifier rect object
+ */
+function includeScroll(rect, element) {
+ var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+ var scrollTop = getScroll(element, 'top');
+ var scrollLeft = getScroll(element, 'left');
+ var modifier = subtract ? -1 : 1;
+ rect.top += scrollTop * modifier;
+ rect.bottom += scrollTop * modifier;
+ rect.left += scrollLeft * modifier;
+ rect.right += scrollLeft * modifier;
+ return rect;
+}
+
+/*
+ * Helper to detect borders of a given element
+ * @method
+ * @memberof Popper.Utils
+ * @param {CSSStyleDeclaration} styles
+ * Result of `getStyleComputedProperty` on the given element
+ * @param {String} axis - `x` or `y`
+ * @return {number} borders - The borders size of the given axis
+ */
- if (isHTMLElement(node) && isScrollParent(node)) {
- return node;
- }
+function getBordersSize(styles, axis) {
+ var sideA = axis === 'x' ? 'Left' : 'Top';
+ var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
- return getScrollParent(getParentNode(node));
- }
+ return parseFloat(styles['border' + sideA + 'Width']) + parseFloat(styles['border' + sideB + 'Width']);
+}
- /*
- given a DOM element, return the list of all scroll parents, up the list of ancesors
- until we get to the top window object. This list is what we attach scroll listeners
- to, because if any of these parent elements scroll, we'll need to re-calculate the
- reference element's position.
- */
+function getSize(axis, body, html, computedStyle) {
+ 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);
+}
- function listScrollParents(element, list) {
- if (list === void 0) {
- list = [];
- }
+function getWindowSizes(document) {
+ var body = document.body;
+ var html = document.documentElement;
+ var computedStyle = isIE(10) && getComputedStyle(html);
- var scrollParent = getScrollParent(element);
- var isBody = getNodeName(scrollParent) === 'body';
- var win = getWindow(scrollParent);
- var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
- var updatedList = list.concat(target);
- return isBody ? updatedList : // $FlowFixMe: isBody tells us target will be an HTMLElement here
- updatedList.concat(listScrollParents(getParentNode(target)));
- }
+ return {
+ height: getSize('Height', body, html, computedStyle),
+ width: getSize('Width', body, html, computedStyle)
+ };
+}
- function isTableElement(element) {
- return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
+var classCallCheck = function (instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
}
-
- function getTrueOffsetParent(element) {
- if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
- getComputedStyle(element).position === 'fixed') {
- return null;
+};
+
+var createClass = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
}
+ }
- var offsetParent = element.offsetParent;
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+}();
- if (offsetParent) {
- var html = getDocumentElement(offsetParent);
- if (getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static' && getComputedStyle(html).position !== 'static') {
- return html;
- }
- }
- return offsetParent;
- } // `.offsetParent` reports `null` for fixed elements, while absolute elements
- // return the containing block
- function getContainingBlock(element) {
- var currentNode = getParentNode(element);
+var defineProperty = function (obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value: value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
- while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
- var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
- // create a containing block.
+ return obj;
+};
- if (css.transform !== 'none' || css.perspective !== 'none' || css.willChange && css.willChange !== 'auto') {
- return currentNode;
- } else {
- currentNode = currentNode.parentNode;
+var _extends = Object.assign || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+
+ for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
}
}
+ }
- return null;
- } // Gets the closest ancestor positioned element. Handles some edge cases,
- // such as table ancestors and cross browser bugs.
-
+ return target;
+};
- function getOffsetParent(element) {
- var window = getWindow(element);
- var offsetParent = getTrueOffsetParent(element);
+/**
+ * Given element offsets, generate an output similar to getBoundingClientRect
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Object} offsets
+ * @returns {Object} ClientRect like output
+ */
+function getClientRect(offsets) {
+ return _extends({}, offsets, {
+ right: offsets.left + offsets.width,
+ bottom: offsets.top + offsets.height
+ });
+}
- while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
- offsetParent = getTrueOffsetParent(offsetParent);
+/**
+ * Get bounding client rect of given element
+ * @method
+ * @memberof Popper.Utils
+ * @param {HTMLElement} element
+ * @return {Object} client rect
+ */
+function getBoundingClientRect(element) {
+ var rect = {};
+
+ // IE10 10 FIX: Please, don't ask, the element isn't
+ // considered in DOM in some circumstances...
+ // This isn't reproducible in IE10 compatibility mode of IE11
+ try {
+ if (isIE(10)) {
+ rect = element.getBoundingClientRect();
+ var scrollTop = getScroll(element, 'top');
+ var scrollLeft = getScroll(element, 'left');
+ rect.top += scrollTop;
+ rect.left += scrollLeft;
+ rect.bottom += scrollTop;
+ rect.right += scrollLeft;
+ } else {
+ rect = element.getBoundingClientRect();
}
+ } catch (e) {}
- if (offsetParent && getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static') {
- return window;
- }
+ var result = {
+ left: rect.left,
+ top: rect.top,
+ width: rect.right - rect.left,
+ height: rect.bottom - rect.top
+ };
- return offsetParent || getContainingBlock(element) || window;
- }
-
- var top = 'top';
- var bottom = 'bottom';
- var right = 'right';
- var left = 'left';
- var auto = 'auto';
- var basePlacements = [top, bottom, right, left];
- var start = 'start';
- var end = 'end';
- var clippingParents = 'clippingParents';
- var viewport = 'viewport';
- var popper = 'popper';
- var reference = 'reference';
- var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {
- return acc.concat([placement + "-" + start, placement + "-" + end]);
- }, []);
- var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {
- return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
- }, []); // modifiers that need to read the DOM
-
- var beforeRead = 'beforeRead';
- var read = 'read';
- var afterRead = 'afterRead'; // pure-logic modifiers
-
- var beforeMain = 'beforeMain';
- var main = 'main';
- var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
-
- var beforeWrite = 'beforeWrite';
- var write = 'write';
- var afterWrite = 'afterWrite';
- var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
-
- function order(modifiers) {
- var map = new Map();
- var visited = new Set();
- var result = [];
- modifiers.forEach(function (modifier) {
- map.set(modifier.name, modifier);
- }); // On visiting object, check for its dependencies and visit them recursively
-
- function sort(modifier) {
- visited.add(modifier.name);
- var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
- requires.forEach(function (dep) {
- if (!visited.has(dep)) {
- var depModifier = map.get(dep);
-
- if (depModifier) {
- sort(depModifier);
- }
- }
- });
- result.push(modifier);
- }
+ // subtract scrollbar size from sizes
+ var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
+ var width = sizes.width || element.clientWidth || result.width;
+ var height = sizes.height || element.clientHeight || result.height;
- modifiers.forEach(function (modifier) {
- if (!visited.has(modifier.name)) {
- // check for visited object
- sort(modifier);
- }
- });
- return result;
- }
-
- function orderModifiers(modifiers) {
- // order based on dependencies
- var orderedModifiers = order(modifiers); // order based on phase
-
- return modifierPhases.reduce(function (acc, phase) {
- return acc.concat(orderedModifiers.filter(function (modifier) {
- return modifier.phase === phase;
- }));
- }, []);
- }
-
- function debounce(fn) {
- var pending;
- return function () {
- if (!pending) {
- pending = new Promise(function (resolve) {
- Promise.resolve().then(function () {
- pending = undefined;
- resolve(fn());
- });
- });
- }
+ var horizScrollbar = element.offsetWidth - width;
+ var vertScrollbar = element.offsetHeight - height;
- return pending;
- };
+ // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
+ // we make this check conditional for performance reasons
+ if (horizScrollbar || vertScrollbar) {
+ var styles = getStyleComputedProperty(element);
+ horizScrollbar -= getBordersSize(styles, 'x');
+ vertScrollbar -= getBordersSize(styles, 'y');
+
+ result.width -= horizScrollbar;
+ result.height -= vertScrollbar;
}
- function format(str) {
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- args[_key - 1] = arguments[_key];
- }
+ return getClientRect(result);
+}
- return [].concat(args).reduce(function (p, c) {
- return p.replace(/%s/, c);
- }, str);
- }
-
- var INVALID_MODIFIER_ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s';
- var MISSING_DEPENDENCY_ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available';
- var VALID_PROPERTIES = ['name', 'enabled', 'phase', 'fn', 'effect', 'requires', 'options'];
- function validateModifiers(modifiers) {
- modifiers.forEach(function (modifier) {
- Object.keys(modifier).forEach(function (key) {
- switch (key) {
- case 'name':
- if (typeof modifier.name !== 'string') {
- console.error(format(INVALID_MODIFIER_ERROR, String(modifier.name), '"name"', '"string"', "\"" + String(modifier.name) + "\""));
- }
-
- break;
-
- case 'enabled':
- if (typeof modifier.enabled !== 'boolean') {
- console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"enabled"', '"boolean"', "\"" + String(modifier.enabled) + "\""));
- }
-
- case 'phase':
- if (modifierPhases.indexOf(modifier.phase) < 0) {
- console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"phase"', "either " + modifierPhases.join(', '), "\"" + String(modifier.phase) + "\""));
- }
-
- break;
-
- case 'fn':
- if (typeof modifier.fn !== 'function') {
- console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"fn"', '"function"', "\"" + String(modifier.fn) + "\""));
- }
-
- break;
-
- case 'effect':
- if (typeof modifier.effect !== 'function') {
- console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"effect"', '"function"', "\"" + String(modifier.fn) + "\""));
- }
-
- break;
-
- case 'requires':
- if (!Array.isArray(modifier.requires)) {
- console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requires"', '"array"', "\"" + String(modifier.requires) + "\""));
- }
-
- break;
-
- case 'requiresIfExists':
- if (!Array.isArray(modifier.requiresIfExists)) {
- console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requiresIfExists"', '"array"', "\"" + String(modifier.requiresIfExists) + "\""));
- }
-
- break;
-
- case 'options':
- case 'data':
- break;
-
- default:
- console.error("PopperJS: an invalid property has been provided to the \"" + modifier.name + "\" modifier, valid properties are " + VALID_PROPERTIES.map(function (s) {
- return "\"" + s + "\"";
- }).join(', ') + "; but \"" + key + "\" was provided.");
- }
-
- modifier.requires && modifier.requires.forEach(function (requirement) {
- if (modifiers.find(function (mod) {
- return mod.name === requirement;
- }) == null) {
- console.error(format(MISSING_DEPENDENCY_ERROR, String(modifier.name), requirement, requirement));
- }
- });
- });
- });
- }
+function getOffsetRectRelativeToArbitraryNode(children, parent) {
+ var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
- function uniqueBy(arr, fn) {
- var identifiers = new Set();
- return arr.filter(function (item) {
- var identifier = fn(item);
+ var isIE10 = isIE(10);
+ var isHTML = parent.nodeName === 'HTML';
+ var childrenRect = getBoundingClientRect(children);
+ var parentRect = getBoundingClientRect(parent);
+ var scrollParent = getScrollParent(children);
- if (!identifiers.has(identifier)) {
- identifiers.add(identifier);
- return true;
- }
- });
+ var styles = getStyleComputedProperty(parent);
+ var borderTopWidth = parseFloat(styles.borderTopWidth);
+ var borderLeftWidth = parseFloat(styles.borderLeftWidth);
+
+ // In cases where the parent is fixed, we must ignore negative scroll in offset calc
+ if (fixedPosition && isHTML) {
+ parentRect.top = Math.max(parentRect.top, 0);
+ parentRect.left = Math.max(parentRect.left, 0);
+ }
+ var offsets = getClientRect({
+ top: childrenRect.top - parentRect.top - borderTopWidth,
+ left: childrenRect.left - parentRect.left - borderLeftWidth,
+ width: childrenRect.width,
+ height: childrenRect.height
+ });
+ offsets.marginTop = 0;
+ offsets.marginLeft = 0;
+
+ // Subtract margins of documentElement in case it's being used as parent
+ // we do this only on HTML because it's the only element that behaves
+ // differently when margins are applied to it. The margins are included in
+ // the box of the documentElement, in the other cases not.
+ if (!isIE10 && isHTML) {
+ var marginTop = parseFloat(styles.marginTop);
+ var marginLeft = parseFloat(styles.marginLeft);
+
+ offsets.top -= borderTopWidth - marginTop;
+ offsets.bottom -= borderTopWidth - marginTop;
+ offsets.left -= borderLeftWidth - marginLeft;
+ offsets.right -= borderLeftWidth - marginLeft;
+
+ // Attach marginTop and marginLeft because in some circumstances we may need them
+ offsets.marginTop = marginTop;
+ offsets.marginLeft = marginLeft;
}
- function getBasePlacement(placement) {
- return placement.split('-')[0];
+ if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
+ offsets = includeScroll(offsets, parent);
}
- function mergeByName(modifiers) {
- var merged = modifiers.reduce(function (merged, current) {
- var existing = merged[current.name];
- merged[current.name] = existing ? Object.assign(Object.assign(Object.assign({}, existing), current), {}, {
- options: Object.assign(Object.assign({}, existing.options), current.options),
- data: Object.assign(Object.assign({}, existing.data), current.data)
- }) : current;
- return merged;
- }, {}); // IE11 does not support Object.values
+ return offsets;
+}
- return Object.keys(merged).map(function (key) {
- return merged[key];
- });
- }
+function getViewportOffsetRectRelativeToArtbitraryNode(element) {
+ var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- function getViewportRect(element) {
- var win = getWindow(element);
- var html = getDocumentElement(element);
- var visualViewport = win.visualViewport;
- var width = html.clientWidth;
- var height = html.clientHeight;
- var x = 0;
- var y = 0; // NB: This isn't supported on iOS <= 12. If the keyboard is open, the popper
- // can be obscured underneath it.
- // Also, `html.clientHeight` adds the bottom bar height in Safari iOS, even
- // if it isn't open, so if this isn't available, the popper will be detected
- // to overflow the bottom of the screen too early.
-
- if (visualViewport) {
- width = visualViewport.width;
- height = visualViewport.height; // Uses Layout Viewport (like Chrome; Safari does not currently)
- // In Chrome, it returns a value very close to 0 (+/-) but contains rounding
- // errors due to floating point numbers, so we need to check precision.
- // Safari returns a number <= 0, usually < -1 when pinch-zoomed
- // Feature detection fails in mobile emulation mode in Chrome.
- // Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) <
- // 0.001
- // Fallback here: "Not Safari" userAgent
-
- if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
- x = visualViewport.offsetLeft;
- y = visualViewport.offsetTop;
- }
- }
+ var html = element.ownerDocument.documentElement;
+ var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
+ var width = Math.max(html.clientWidth, window.innerWidth || 0);
+ var height = Math.max(html.clientHeight, window.innerHeight || 0);
- return {
- width: width,
- height: height,
- x: x + getWindowScrollBarX(element),
- y: y
- };
+ var scrollTop = !excludeScroll ? getScroll(html) : 0;
+ var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
+
+ var offset = {
+ top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
+ left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
+ width: width,
+ height: height
+ };
+
+ return getClientRect(offset);
+}
+
+/**
+ * Check if the given element is fixed or is inside a fixed parent
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @argument {Element} customContainer
+ * @returns {Boolean} answer to "isFixed?"
+ */
+function isFixed(element) {
+ var nodeName = element.nodeName;
+ if (nodeName === 'BODY' || nodeName === 'HTML') {
+ return false;
+ }
+ if (getStyleComputedProperty(element, 'position') === 'fixed') {
+ return true;
+ }
+ var parentNode = getParentNode(element);
+ if (!parentNode) {
+ return false;
}
+ return isFixed(parentNode);
+}
- // of the `` and `
` rect bounds if horizontally scrollable
+/**
+ * Finds the first parent of an element that has a transformed property defined
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} first transformed parent or documentElement
+ */
- function getDocumentRect(element) {
- var html = getDocumentElement(element);
- var winScroll = getWindowScroll(element);
- var body = element.ownerDocument.body;
- var width = Math.max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
- var height = Math.max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
- var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
- var y = -winScroll.scrollTop;
+function getFixedPositionOffsetParent(element) {
+ // This check is needed to avoid errors in case one of the elements isn't defined for any reason
+ if (!element || !element.parentElement || isIE()) {
+ return document.documentElement;
+ }
+ var el = element.parentElement;
+ while (el && getStyleComputedProperty(el, 'transform') === 'none') {
+ el = el.parentElement;
+ }
+ return el || document.documentElement;
+}
- if (getComputedStyle(body || html).direction === 'rtl') {
- x += Math.max(html.clientWidth, body ? body.clientWidth : 0) - width;
+/**
+ * Computed the boundaries limits and return them
+ * @method
+ * @memberof Popper.Utils
+ * @param {HTMLElement} popper
+ * @param {HTMLElement} reference
+ * @param {number} padding
+ * @param {HTMLElement} boundariesElement - Element used to define the boundaries
+ * @param {Boolean} fixedPosition - Is in fixed position mode
+ * @returns {Object} Coordinates of the boundaries
+ */
+function getBoundaries(popper, reference, padding, boundariesElement) {
+ var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
+
+ // NOTE: 1 DOM access here
+
+ var boundaries = { top: 0, left: 0 };
+ var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
+
+ // Handle viewport case
+ if (boundariesElement === 'viewport') {
+ boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
+ } else {
+ // Handle other cases based on DOM element used as boundaries
+ var boundariesNode = void 0;
+ if (boundariesElement === 'scrollParent') {
+ boundariesNode = getScrollParent(getParentNode(reference));
+ if (boundariesNode.nodeName === 'BODY') {
+ boundariesNode = popper.ownerDocument.documentElement;
+ }
+ } else if (boundariesElement === 'window') {
+ boundariesNode = popper.ownerDocument.documentElement;
+ } else {
+ boundariesNode = boundariesElement;
}
- return {
- width: width,
- height: height,
- x: x,
- y: y
- };
- }
+ var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
- function contains(parent, child) {
- // $FlowFixMe: hasOwnProperty doesn't seem to work in tests
- var isShadow = Boolean(child.getRootNode && child.getRootNode().host); // First, attempt with faster native method
+ // In case of HTML, we need a different computation
+ if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
+ var _getWindowSizes = getWindowSizes(popper.ownerDocument),
+ height = _getWindowSizes.height,
+ width = _getWindowSizes.width;
- if (parent.contains(child)) {
- return true;
- } // then fallback to custom implementation with Shadow DOM support
- else if (isShadow) {
- var next = child;
+ boundaries.top += offsets.top - offsets.marginTop;
+ boundaries.bottom = height + offsets.top;
+ boundaries.left += offsets.left - offsets.marginLeft;
+ boundaries.right = width + offsets.left;
+ } else {
+ // for all the other DOM elements, this one is good
+ boundaries = offsets;
+ }
+ }
- do {
- if (next && parent.isSameNode(next)) {
- return true;
- } // $FlowFixMe: need a better way to handle this...
+ // Add paddings
+ padding = padding || 0;
+ var isPaddingNumber = typeof padding === 'number';
+ boundaries.left += isPaddingNumber ? padding : padding.left || 0;
+ boundaries.top += isPaddingNumber ? padding : padding.top || 0;
+ boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
+ boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
+ return boundaries;
+}
- next = next.parentNode || next.host;
- } while (next);
- } // Give up, the result is false
+function getArea(_ref) {
+ var width = _ref.width,
+ height = _ref.height;
+ return width * height;
+}
- return false;
- }
+/**
+ * Utility used to transform the `auto` placement to the placement with more
+ * available space.
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
+ var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
- function rectToClientRect(rect) {
- return Object.assign(Object.assign({}, rect), {}, {
- left: rect.x,
- top: rect.y,
- right: rect.x + rect.width,
- bottom: rect.y + rect.height
- });
+ if (placement.indexOf('auto') === -1) {
+ return placement;
}
- function getInnerBoundingClientRect(element) {
- var rect = getBoundingClientRect(element);
- rect.top = rect.top + element.clientTop;
- rect.left = rect.left + element.clientLeft;
- rect.bottom = rect.top + element.clientHeight;
- rect.right = rect.left + element.clientWidth;
- rect.width = element.clientWidth;
- rect.height = element.clientHeight;
- rect.x = rect.left;
- rect.y = rect.top;
- return rect;
- }
+ var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
+
+ var rects = {
+ top: {
+ width: boundaries.width,
+ height: refRect.top - boundaries.top
+ },
+ right: {
+ width: boundaries.right - refRect.right,
+ height: boundaries.height
+ },
+ bottom: {
+ width: boundaries.width,
+ height: boundaries.bottom - refRect.bottom
+ },
+ left: {
+ width: refRect.left - boundaries.left,
+ height: boundaries.height
+ }
+ };
- function getClientRectFromMixedType(element, clippingParent) {
- return clippingParent === viewport ? rectToClientRect(getViewportRect(element)) : isHTMLElement(clippingParent) ? getInnerBoundingClientRect(clippingParent) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
- } // A "clipping parent" is an overflowable container with the characteristic of
- // clipping (or hiding) overflowing elements with a position different from
- // `initial`
+ var sortedAreas = Object.keys(rects).map(function (key) {
+ return _extends({
+ key: key
+ }, rects[key], {
+ area: getArea(rects[key])
+ });
+ }).sort(function (a, b) {
+ return b.area - a.area;
+ });
+ var filteredAreas = sortedAreas.filter(function (_ref2) {
+ var width = _ref2.width,
+ height = _ref2.height;
+ return width >= popper.clientWidth && height >= popper.clientHeight;
+ });
- function getClippingParents(element) {
- var clippingParents = listScrollParents(getParentNode(element));
- var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;
- var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
+ var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
- if (!isElement(clipperElement)) {
- return [];
- } // $FlowFixMe: https://github.com/facebook/flow/issues/1414
+ var variation = placement.split('-')[1];
+ return computedPlacement + (variation ? '-' + variation : '');
+}
- return clippingParents.filter(function (clippingParent) {
- return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';
- });
- } // Gets the maximum area that the element is visible in due to any number of
- // clipping parents
-
-
- function getClippingRect(element, boundary, rootBoundary) {
- var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
- var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
- var firstClippingParent = clippingParents[0];
- var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
- var rect = getClientRectFromMixedType(element, clippingParent);
- accRect.top = Math.max(rect.top, accRect.top);
- accRect.right = Math.min(rect.right, accRect.right);
- accRect.bottom = Math.min(rect.bottom, accRect.bottom);
- accRect.left = Math.max(rect.left, accRect.left);
- return accRect;
- }, getClientRectFromMixedType(element, firstClippingParent));
- clippingRect.width = clippingRect.right - clippingRect.left;
- clippingRect.height = clippingRect.bottom - clippingRect.top;
- clippingRect.x = clippingRect.left;
- clippingRect.y = clippingRect.top;
- return clippingRect;
- }
-
- function getVariation(placement) {
- return placement.split('-')[1];
- }
-
- function getMainAxisFromPlacement(placement) {
- return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
- }
-
- function computeOffsets(_ref) {
- var reference = _ref.reference,
- element = _ref.element,
- placement = _ref.placement;
- var basePlacement = placement ? getBasePlacement(placement) : null;
- var variation = placement ? getVariation(placement) : null;
- var commonX = reference.x + reference.width / 2 - element.width / 2;
- var commonY = reference.y + reference.height / 2 - element.height / 2;
- var offsets;
-
- switch (basePlacement) {
- case top:
- offsets = {
- x: commonX,
- y: reference.y - element.height
- };
- break;
+/**
+ * Get offsets to the reference element
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} state
+ * @param {Element} popper - the popper element
+ * @param {Element} reference - the reference element (the popper will be relative to this)
+ * @param {Element} fixedPosition - is in fixed position mode
+ * @returns {Object} An object containing the offsets which will be applied to the popper
+ */
+function getReferenceOffsets(state, popper, reference) {
+ var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
- case bottom:
- offsets = {
- x: commonX,
- y: reference.y + reference.height
- };
- break;
+ var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
+ return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
+}
- case right:
- offsets = {
- x: reference.x + reference.width,
- y: commonY
- };
- break;
+/**
+ * Get the outer sizes of the given element (offset size + margins)
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Object} object containing width and height properties
+ */
+function getOuterSizes(element) {
+ var window = element.ownerDocument.defaultView;
+ var styles = window.getComputedStyle(element);
+ var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
+ var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
+ var result = {
+ width: element.offsetWidth + y,
+ height: element.offsetHeight + x
+ };
+ return result;
+}
- case left:
- offsets = {
- x: reference.x - element.width,
- y: commonY
- };
- break;
+/**
+ * Get the opposite placement of the given one
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement
+ * @returns {String} flipped placement
+ */
+function getOppositePlacement(placement) {
+ var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
+ return placement.replace(/left|right|bottom|top/g, function (matched) {
+ return hash[matched];
+ });
+}
- default:
- offsets = {
- x: reference.x,
- y: reference.y
- };
- }
+/**
+ * Get offsets to the popper
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} position - CSS position the Popper will get applied
+ * @param {HTMLElement} popper - the popper element
+ * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
+ * @param {String} placement - one of the valid placement options
+ * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
+ */
+function getPopperOffsets(popper, referenceOffsets, placement) {
+ placement = placement.split('-')[0];
- var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
+ // Get popper node sizes
+ var popperRect = getOuterSizes(popper);
- if (mainAxis != null) {
- var len = mainAxis === 'y' ? 'height' : 'width';
+ // Add position, width and height to our offsets object
+ var popperOffsets = {
+ width: popperRect.width,
+ height: popperRect.height
+ };
- switch (variation) {
- case start:
- offsets[mainAxis] = Math.floor(offsets[mainAxis]) - Math.floor(reference[len] / 2 - element[len] / 2);
- break;
+ // depending by the popper placement we have to compute its offsets slightly differently
+ var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
+ var mainSide = isHoriz ? 'top' : 'left';
+ var secondarySide = isHoriz ? 'left' : 'top';
+ var measurement = isHoriz ? 'height' : 'width';
+ var secondaryMeasurement = !isHoriz ? 'height' : 'width';
+
+ popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
+ if (placement === secondarySide) {
+ popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
+ } else {
+ popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
+ }
- case end:
- offsets[mainAxis] = Math.floor(offsets[mainAxis]) + Math.ceil(reference[len] / 2 - element[len] / 2);
- break;
- }
- }
+ return popperOffsets;
+}
- return offsets;
+/**
+ * Mimics the `find` method of Array
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Array} arr
+ * @argument prop
+ * @argument value
+ * @returns index or -1
+ */
+function find(arr, check) {
+ // use native find if supported
+ if (Array.prototype.find) {
+ return arr.find(check);
}
- function getFreshSideObject() {
- return {
- top: 0,
- right: 0,
- bottom: 0,
- left: 0
- };
- }
+ // use `filter` to obtain the same behavior of `find`
+ return arr.filter(check)[0];
+}
- function mergePaddingObject(paddingObject) {
- return Object.assign(Object.assign({}, getFreshSideObject()), paddingObject);
+/**
+ * Return the index of the matching object
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Array} arr
+ * @argument prop
+ * @argument value
+ * @returns index or -1
+ */
+function findIndex(arr, prop, value) {
+ // use native findIndex if supported
+ if (Array.prototype.findIndex) {
+ return arr.findIndex(function (cur) {
+ return cur[prop] === value;
+ });
}
- function expandToHashMap(value, keys) {
- return keys.reduce(function (hashMap, key) {
- hashMap[key] = value;
- return hashMap;
- }, {});
- }
+ // use `find` + `indexOf` if `findIndex` isn't supported
+ var match = find(arr, function (obj) {
+ return obj[prop] === value;
+ });
+ return arr.indexOf(match);
+}
- function detectOverflow(state, options) {
- if (options === void 0) {
- options = {};
- }
+/**
+ * Loop trough the list of modifiers and run them in order,
+ * each of them will then edit the data object.
+ * @method
+ * @memberof Popper.Utils
+ * @param {dataObject} data
+ * @param {Array} modifiers
+ * @param {String} ends - Optional modifier name used as stopper
+ * @returns {dataObject}
+ */
+function runModifiers(modifiers, data, ends) {
+ var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
- var _options = options,
- _options$placement = _options.placement,
- placement = _options$placement === void 0 ? state.placement : _options$placement,
- _options$boundary = _options.boundary,
- boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,
- _options$rootBoundary = _options.rootBoundary,
- rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,
- _options$elementConte = _options.elementContext,
- elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,
- _options$altBoundary = _options.altBoundary,
- altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,
- _options$padding = _options.padding,
- padding = _options$padding === void 0 ? 0 : _options$padding;
- var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
- var altContext = elementContext === popper ? reference : popper;
- var referenceElement = state.elements.reference;
- var popperRect = state.rects.popper;
- var element = state.elements[altBoundary ? altContext : elementContext];
- var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary);
- var referenceClientRect = getBoundingClientRect(referenceElement);
- var popperOffsets = computeOffsets({
- reference: referenceClientRect,
- element: popperRect,
- strategy: 'absolute',
- placement: placement
- });
- var popperClientRect = rectToClientRect(Object.assign(Object.assign({}, popperRect), popperOffsets));
- var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect
- // 0 or negative = within the clipping rect
-
- var overflowOffsets = {
- top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
- bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
- left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
- right: elementClientRect.right - clippingClientRect.right + paddingObject.right
- };
- var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element
-
- if (elementContext === popper && offsetData) {
- var offset = offsetData[placement];
- Object.keys(overflowOffsets).forEach(function (key) {
- var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
- var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
- overflowOffsets[key] += offset[axis] * multiply;
- });
+ modifiersToRun.forEach(function (modifier) {
+ if (modifier['function']) {
+ // eslint-disable-line dot-notation
+ console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
+ }
+ var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
+ if (modifier.enabled && isFunction(fn)) {
+ // Add properties to offsets to make them a complete clientRect object
+ // we do this before each modifier to make sure the previous one doesn't
+ // mess with these values
+ data.offsets.popper = getClientRect(data.offsets.popper);
+ data.offsets.reference = getClientRect(data.offsets.reference);
+
+ data = fn(data, modifier);
}
+ });
- return overflowOffsets;
+ return data;
+}
+
+/**
+ * Updates the position of the popper, computing the new offsets and applying
+ * the new style.
+ * Prefer `scheduleUpdate` over `update` because of performance reasons.
+ * @method
+ * @memberof Popper
+ */
+function update() {
+ // if popper is destroyed, don't perform any further update
+ if (this.state.isDestroyed) {
+ return;
}
- var INVALID_ELEMENT_ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.';
- var INFINITE_LOOP_ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.';
- var DEFAULT_OPTIONS = {
- placement: 'bottom',
- modifiers: [],
- strategy: 'absolute'
+ var data = {
+ instance: this,
+ styles: {},
+ arrowStyles: {},
+ attributes: {},
+ flipped: false,
+ offsets: {}
};
- function areValidElements() {
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
+ // compute reference element offsets
+ data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
- return !args.some(function (element) {
- return !(element && typeof element.getBoundingClientRect === 'function');
- });
- }
+ // compute auto placement, store placement inside the data object,
+ // modifiers will be able to edit `placement` if needed
+ // and refer to originalPlacement to know the original value
+ data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
- function popperGenerator(generatorOptions) {
- if (generatorOptions === void 0) {
- generatorOptions = {};
- }
+ // store the computed placement inside `originalPlacement`
+ data.originalPlacement = data.placement;
- var _generatorOptions = generatorOptions,
- _generatorOptions$def = _generatorOptions.defaultModifiers,
- defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
- _generatorOptions$def2 = _generatorOptions.defaultOptions,
- defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
- return function createPopper(reference, popper, options) {
- if (options === void 0) {
- options = defaultOptions;
- }
+ data.positionFixed = this.options.positionFixed;
- var state = {
- placement: 'bottom',
- orderedModifiers: [],
- options: Object.assign(Object.assign({}, DEFAULT_OPTIONS), defaultOptions),
- modifiersData: {},
- elements: {
- reference: reference,
- popper: popper
- },
- attributes: {},
- styles: {}
- };
- var effectCleanupFns = [];
- var isDestroyed = false;
- var instance = {
- state: state,
- setOptions: function setOptions(options) {
- cleanupModifierEffects();
- state.options = Object.assign(Object.assign(Object.assign({}, defaultOptions), state.options), options);
- state.scrollParents = {
- reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
- popper: listScrollParents(popper)
- }; // Orders the modifiers based on their dependencies and `phase`
- // properties
-
- var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
-
- state.orderedModifiers = orderedModifiers.filter(function (m) {
- return m.enabled;
- }); // Validate the provided modifiers so that the consumer will get warned
- // if one of the modifiers is invalid for any reason
-
- {
- var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function (_ref) {
- var name = _ref.name;
- return name;
- });
- validateModifiers(modifiers);
-
- if (getBasePlacement(state.options.placement) === auto) {
- var flipModifier = state.orderedModifiers.find(function (_ref2) {
- var name = _ref2.name;
- return name === 'flip';
- });
-
- if (!flipModifier) {
- console.error(['Popper: "auto" placements require the "flip" modifier be', 'present and enabled to work.'].join(' '));
- }
- }
-
- var _getComputedStyle = getComputedStyle(popper),
- marginTop = _getComputedStyle.marginTop,
- marginRight = _getComputedStyle.marginRight,
- marginBottom = _getComputedStyle.marginBottom,
- marginLeft = _getComputedStyle.marginLeft; // We no longer take into account `margins` on the popper, and it can
- // cause bugs with positioning, so we'll warn the consumer
-
-
- if ([marginTop, marginRight, marginBottom, marginLeft].some(function (margin) {
- return parseFloat(margin);
- })) {
- console.warn(['Popper: CSS "margin" styles cannot be used to apply padding', 'between the popper and its reference element or boundary.', 'To replicate margin, use the `offset` modifier, as well as', 'the `padding` option in the `preventOverflow` and `flip`', 'modifiers.'].join(' '));
- }
- }
-
- runModifierEffects();
- return instance.update();
- },
- // Sync update – it will always be executed, even if not necessary. This
- // is useful for low frequency updates where sync behavior simplifies the
- // logic.
- // For high frequency updates (e.g. `resize` and `scroll` events), always
- // prefer the async Popper#update method
- forceUpdate: function forceUpdate() {
- if (isDestroyed) {
- return;
- }
-
- var _state$elements = state.elements,
- reference = _state$elements.reference,
- popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
- // anymore
-
- if (!areValidElements(reference, popper)) {
- {
- console.error(INVALID_ELEMENT_ERROR);
- }
-
- return;
- } // Store the reference and popper rects to be read by modifiers
-
-
- state.rects = {
- reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
- popper: getLayoutRect(popper)
- }; // Modifiers have the ability to reset the current update cycle. The
- // most common use case for this is the `flip` modifier changing the
- // placement, which then needs to re-run all the modifiers, because the
- // logic was previously ran for the previous placement and is therefore
- // stale/incorrect
-
- state.reset = false;
- state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
- // is filled with the initial data specified by the modifier. This means
- // it doesn't persist and is fresh on each update.
- // To ensure persistent data, use `${name}#persistent`
-
- state.orderedModifiers.forEach(function (modifier) {
- return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
- });
- var __debug_loops__ = 0;
-
- for (var index = 0; index < state.orderedModifiers.length; index++) {
- {
- __debug_loops__ += 1;
-
- if (__debug_loops__ > 100) {
- console.error(INFINITE_LOOP_ERROR);
- break;
- }
- }
-
- if (state.reset === true) {
- state.reset = false;
- index = -1;
- continue;
- }
-
- var _state$orderedModifie = state.orderedModifiers[index],
- fn = _state$orderedModifie.fn,
- _state$orderedModifie2 = _state$orderedModifie.options,
- _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
- name = _state$orderedModifie.name;
-
- if (typeof fn === 'function') {
- state = fn({
- state: state,
- options: _options,
- name: name,
- instance: instance
- }) || state;
- }
- }
- },
- // Async and optimistically optimized update – it will not be executed if
- // not necessary (debounced to run at most once-per-tick)
- update: debounce(function () {
- return new Promise(function (resolve) {
- instance.forceUpdate();
- resolve(state);
- });
- }),
- destroy: function destroy() {
- cleanupModifierEffects();
- isDestroyed = true;
- }
- };
-
- if (!areValidElements(reference, popper)) {
- {
- console.error(INVALID_ELEMENT_ERROR);
- }
-
- return instance;
- }
+ // compute the popper offsets
+ data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
- instance.setOptions(options).then(function (state) {
- if (!isDestroyed && options.onFirstUpdate) {
- options.onFirstUpdate(state);
- }
- }); // Modifiers have the ability to execute arbitrary code before the first
- // update cycle runs. They will be executed in the same order as the update
- // cycle. This is useful when a modifier adds some persistent data that
- // other modifiers need to use, but the modifier is run after the dependent
- // one.
-
- function runModifierEffects() {
- state.orderedModifiers.forEach(function (_ref3) {
- var name = _ref3.name,
- _ref3$options = _ref3.options,
- options = _ref3$options === void 0 ? {} : _ref3$options,
- effect = _ref3.effect;
-
- if (typeof effect === 'function') {
- var cleanupFn = effect({
- state: state,
- name: name,
- instance: instance,
- options: options
- });
-
- var noopFn = function noopFn() {};
-
- effectCleanupFns.push(cleanupFn || noopFn);
- }
- });
- }
+ data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
- function cleanupModifierEffects() {
- effectCleanupFns.forEach(function (fn) {
- return fn();
- });
- effectCleanupFns = [];
- }
+ // run the modifiers
+ data = runModifiers(this.modifiers, data);
- return instance;
- };
+ // the first `update` will call `onCreate` callback
+ // the other ones will call `onUpdate` callback
+ if (!this.state.isCreated) {
+ this.state.isCreated = true;
+ this.options.onCreate(data);
+ } else {
+ this.options.onUpdate(data);
}
+}
- var passive = {
- passive: true
- };
+/**
+ * Helper used to know if the given modifier is enabled.
+ * @method
+ * @memberof Popper.Utils
+ * @returns {Boolean}
+ */
+function isModifierEnabled(modifiers, modifierName) {
+ return modifiers.some(function (_ref) {
+ var name = _ref.name,
+ enabled = _ref.enabled;
+ return enabled && name === modifierName;
+ });
+}
- function effect(_ref) {
- var state = _ref.state,
- instance = _ref.instance,
- options = _ref.options;
- var _options$scroll = options.scroll,
- scroll = _options$scroll === void 0 ? true : _options$scroll,
- _options$resize = options.resize,
- resize = _options$resize === void 0 ? true : _options$resize;
- var window = getWindow(state.elements.popper);
- var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);
-
- if (scroll) {
- scrollParents.forEach(function (scrollParent) {
- scrollParent.addEventListener('scroll', instance.update, passive);
- });
+/**
+ * Get the prefixed supported property name
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} property (camelCase)
+ * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
+ */
+function getSupportedPropertyName(property) {
+ var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
+ var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
+
+ for (var i = 0; i < prefixes.length; i++) {
+ var prefix = prefixes[i];
+ var toCheck = prefix ? '' + prefix + upperProp : property;
+ if (typeof document.body.style[toCheck] !== 'undefined') {
+ return toCheck;
}
+ }
+ return null;
+}
- if (resize) {
- window.addEventListener('resize', instance.update, passive);
- }
+/**
+ * Destroys the popper.
+ * @method
+ * @memberof Popper
+ */
+function destroy() {
+ this.state.isDestroyed = true;
+
+ // touch DOM only if `applyStyle` modifier is enabled
+ if (isModifierEnabled(this.modifiers, 'applyStyle')) {
+ this.popper.removeAttribute('x-placement');
+ this.popper.style.position = '';
+ this.popper.style.top = '';
+ this.popper.style.left = '';
+ this.popper.style.right = '';
+ this.popper.style.bottom = '';
+ this.popper.style.willChange = '';
+ this.popper.style[getSupportedPropertyName('transform')] = '';
+ }
- return function () {
- if (scroll) {
- scrollParents.forEach(function (scrollParent) {
- scrollParent.removeEventListener('scroll', instance.update, passive);
- });
- }
+ this.disableEventListeners();
- if (resize) {
- window.removeEventListener('resize', instance.update, passive);
- }
- };
- } // eslint-disable-next-line import/no-unused-modules
+ // remove the popper if user explicitly asked for the deletion on destroy
+ // do not use `remove` because IE11 doesn't support it
+ if (this.options.removeOnDestroy) {
+ this.popper.parentNode.removeChild(this.popper);
+ }
+ return this;
+}
+/**
+ * Get the window associated with the element
+ * @argument {Element} element
+ * @returns {Window}
+ */
+function getWindow(element) {
+ var ownerDocument = element.ownerDocument;
+ return ownerDocument ? ownerDocument.defaultView : window;
+}
+
+function attachToScrollParents(scrollParent, event, callback, scrollParents) {
+ var isBody = scrollParent.nodeName === 'BODY';
+ var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
+ target.addEventListener(event, callback, { passive: true });
+
+ if (!isBody) {
+ attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
+ }
+ scrollParents.push(target);
+}
- var eventListeners = {
- name: 'eventListeners',
- enabled: true,
- phase: 'write',
- fn: function fn() {},
- effect: effect,
- data: {}
- };
+/**
+ * Setup needed event listeners used to update the popper position
+ * @method
+ * @memberof Popper.Utils
+ * @private
+ */
+function setupEventListeners(reference, options, state, updateBound) {
+ // Resize event listener on window
+ state.updateBound = updateBound;
+ getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
- function popperOffsets(_ref) {
- var state = _ref.state,
- name = _ref.name;
- // Offsets are the actual position the popper needs to have to be
- // properly positioned near its reference element
- // This is the most basic placement, and will be adjusted by
- // the modifiers in the next step
- state.modifiersData[name] = computeOffsets({
- reference: state.rects.reference,
- element: state.rects.popper,
- strategy: 'absolute',
- placement: state.placement
- });
- } // eslint-disable-next-line import/no-unused-modules
+ // Scroll event listener on scroll parents
+ var scrollElement = getScrollParent(reference);
+ attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
+ state.scrollElement = scrollElement;
+ state.eventsEnabled = true;
+ return state;
+}
- var popperOffsets$1 = {
- name: 'popperOffsets',
- enabled: true,
- phase: 'read',
- fn: popperOffsets,
- data: {}
- };
+/**
+ * It will add resize/scroll events and start recalculating
+ * position of the popper element when they are triggered.
+ * @method
+ * @memberof Popper
+ */
+function enableEventListeners() {
+ if (!this.state.eventsEnabled) {
+ this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
+ }
+}
- var unsetSides = {
- top: 'auto',
- right: 'auto',
- bottom: 'auto',
- left: 'auto'
- }; // Round the offsets to the nearest suitable subpixel based on the DPR.
- // Zooming can change the DPR, but it seems to report a value that will
- // cleanly divide the values into the appropriate subpixels.
-
- function roundOffsets(_ref) {
- var x = _ref.x,
- y = _ref.y;
- var win = window;
- var dpr = win.devicePixelRatio || 1;
- return {
- x: Math.round(x * dpr) / dpr || 0,
- y: Math.round(y * dpr) / dpr || 0
- };
+/**
+ * Remove event listeners used to update the popper position
+ * @method
+ * @memberof Popper.Utils
+ * @private
+ */
+function removeEventListeners(reference, state) {
+ // Remove resize event listener on window
+ getWindow(reference).removeEventListener('resize', state.updateBound);
+
+ // Remove scroll event listener on scroll parents
+ state.scrollParents.forEach(function (target) {
+ target.removeEventListener('scroll', state.updateBound);
+ });
+
+ // Reset state
+ state.updateBound = null;
+ state.scrollParents = [];
+ state.scrollElement = null;
+ state.eventsEnabled = false;
+ return state;
+}
+
+/**
+ * It will remove resize/scroll events and won't recalculate popper position
+ * when they are triggered. It also won't trigger `onUpdate` callback anymore,
+ * unless you call `update` method manually.
+ * @method
+ * @memberof Popper
+ */
+function disableEventListeners() {
+ if (this.state.eventsEnabled) {
+ cancelAnimationFrame(this.scheduleUpdate);
+ this.state = removeEventListeners(this.reference, this.state);
}
+}
- function mapToStyles(_ref2) {
- var _Object$assign2;
+/**
+ * Tells if a given input is a number
+ * @method
+ * @memberof Popper.Utils
+ * @param {*} input to check
+ * @return {Boolean}
+ */
+function isNumeric(n) {
+ return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
+}
- var popper = _ref2.popper,
- popperRect = _ref2.popperRect,
- placement = _ref2.placement,
- offsets = _ref2.offsets,
- position = _ref2.position,
- gpuAcceleration = _ref2.gpuAcceleration,
- adaptive = _ref2.adaptive;
+/**
+ * Set the style to the given popper
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element - Element to apply the style to
+ * @argument {Object} styles
+ * Object with a list of properties and values which will be applied to the element
+ */
+function setStyles(element, styles) {
+ Object.keys(styles).forEach(function (prop) {
+ var unit = '';
+ // add unit if the value is numeric and is one of the following
+ if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
+ unit = 'px';
+ }
+ element.style[prop] = styles[prop] + unit;
+ });
+}
- var _roundOffsets = roundOffsets(offsets),
- x = _roundOffsets.x,
- y = _roundOffsets.y;
+/**
+ * Set the attributes to the given popper
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element - Element to apply the attributes to
+ * @argument {Object} styles
+ * Object with a list of properties and values which will be applied to the element
+ */
+function setAttributes(element, attributes) {
+ Object.keys(attributes).forEach(function (prop) {
+ var value = attributes[prop];
+ if (value !== false) {
+ element.setAttribute(prop, attributes[prop]);
+ } else {
+ element.removeAttribute(prop);
+ }
+ });
+}
- var hasX = offsets.hasOwnProperty('x');
- var hasY = offsets.hasOwnProperty('y');
- var sideX = left;
- var sideY = top;
- var win = window;
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} data.styles - List of style properties - values to apply to popper element
+ * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The same data object
+ */
+function applyStyle(data) {
+ // any property present in `data.styles` will be applied to the popper,
+ // in this way we can make the 3rd party modifiers add custom styles to it
+ // Be aware, modifiers could override the properties defined in the previous
+ // lines of this modifier!
+ setStyles(data.instance.popper, data.styles);
+
+ // any property present in `data.attributes` will be applied to the popper,
+ // they will be set as HTML attributes of the element
+ setAttributes(data.instance.popper, data.attributes);
+
+ // if arrowElement is defined and arrowStyles has some properties
+ if (data.arrowElement && Object.keys(data.arrowStyles).length) {
+ setStyles(data.arrowElement, data.arrowStyles);
+ }
- if (adaptive) {
- var offsetParent = getOffsetParent(popper);
+ return data;
+}
- if (offsetParent === getWindow(popper)) {
- offsetParent = getDocumentElement(popper);
- } // $FlowFixMe: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it
+/**
+ * Set the x-placement attribute before everything else because it could be used
+ * to add margins to the popper margins needs to be calculated to get the
+ * correct popper offsets.
+ * @method
+ * @memberof Popper.modifiers
+ * @param {HTMLElement} reference - The reference element used to position the popper
+ * @param {HTMLElement} popper - The HTML element used as popper
+ * @param {Object} options - Popper.js options
+ */
+function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
+ // compute reference element offsets
+ var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
- /*:: offsetParent = (offsetParent: Element); */
+ // compute auto placement, store placement inside the data object,
+ // modifiers will be able to edit `placement` if needed
+ // and refer to originalPlacement to know the original value
+ var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
+ popper.setAttribute('x-placement', placement);
- if (placement === top) {
- sideY = bottom;
- y -= offsetParent.clientHeight - popperRect.height;
- y *= gpuAcceleration ? 1 : -1;
- }
+ // Apply `position` to popper before anything else because
+ // without the position applied we can't guarantee correct computations
+ setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
- if (placement === left) {
- sideX = right;
- x -= offsetParent.clientWidth - popperRect.width;
- x *= gpuAcceleration ? 1 : -1;
- }
- }
+ return options;
+}
- var commonStyles = Object.assign({
- position: position
- }, adaptive && unsetSides);
+/**
+ * @function
+ * @memberof Popper.Utils
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Boolean} shouldRound - If the offsets should be rounded at all
+ * @returns {Object} The popper's position offsets rounded
+ *
+ * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
+ * good as it can be within reason.
+ * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
+ *
+ * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
+ * as well on High DPI screens).
+ *
+ * Firefox prefers no rounding for positioning and does not have blurriness on
+ * high DPI screens.
+ *
+ * Only horizontal placement and left/right values need to be considered.
+ */
+function getRoundedOffsets(data, shouldRound) {
+ var _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
+ var round = Math.round,
+ floor = Math.floor;
+
+ var noRound = function noRound(v) {
+ return v;
+ };
- if (gpuAcceleration) {
- var _Object$assign;
+ var referenceWidth = round(reference.width);
+ var popperWidth = round(popper.width);
- return Object.assign(Object.assign({}, commonStyles), {}, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) < 2 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign));
- }
+ var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
+ var isVariation = data.placement.indexOf('-') !== -1;
+ var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
+ var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
+
+ var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
+ var verticalToInteger = !shouldRound ? noRound : round;
+
+ return {
+ left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
+ top: verticalToInteger(popper.top),
+ bottom: verticalToInteger(popper.bottom),
+ right: horizontalToInteger(popper.right)
+ };
+}
- return Object.assign(Object.assign({}, commonStyles), {}, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2));
+var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function computeStyle(data, options) {
+ var x = options.x,
+ y = options.y;
+ var popper = data.offsets.popper;
+
+ // Remove this legacy support in Popper.js v2
+
+ var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
+ return modifier.name === 'applyStyle';
+ }).gpuAcceleration;
+ if (legacyGpuAccelerationOption !== undefined) {
+ console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
}
+ var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
- function computeStyles(_ref3) {
- var state = _ref3.state,
- options = _ref3.options;
- var _options$gpuAccelerat = options.gpuAcceleration,
- gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,
- _options$adaptive = options.adaptive,
- adaptive = _options$adaptive === void 0 ? true : _options$adaptive;
+ var offsetParent = getOffsetParent(data.instance.popper);
+ var offsetParentRect = getBoundingClientRect(offsetParent);
- {
- var transitionProperty = getComputedStyle(state.elements.popper).transitionProperty || '';
+ // Styles
+ var styles = {
+ position: popper.position
+ };
- if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) {
- return transitionProperty.indexOf(property) >= 0;
- })) {
- console.warn(['Popper: Detected CSS transitions on at least one of the following', 'CSS properties: "transform", "top", "right", "bottom", "left".', '\n\n', 'Disable the "computeStyles" modifier\'s `adaptive` option to allow', 'for smooth transitions, or remove these properties from the CSS', 'transition declaration on the popper element if only transitioning', 'opacity or background-color for example.', '\n\n', 'We recommend using the popper element as a wrapper around an inner', 'element that can have any CSS property transitioned for animations.'].join(' '));
- }
+ var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
+
+ var sideA = x === 'bottom' ? 'top' : 'bottom';
+ var sideB = y === 'right' ? 'left' : 'right';
+
+ // if gpuAcceleration is set to `true` and transform is supported,
+ // we use `translate3d` to apply the position to the popper we
+ // automatically use the supported prefixed version if needed
+ var prefixedProperty = getSupportedPropertyName('transform');
+
+ // now, let's make a step back and look at this code closely (wtf?)
+ // If the content of the popper grows once it's been positioned, it
+ // may happen that the popper gets misplaced because of the new content
+ // overflowing its reference element
+ // To avoid this problem, we provide two options (x and y), which allow
+ // the consumer to define the offset origin.
+ // If we position a popper on top of a reference element, we can set
+ // `x` to `top` to make the popper grow towards its top instead of
+ // its bottom.
+ var left = void 0,
+ top = void 0;
+ if (sideA === 'bottom') {
+ // when offsetParent is the positioning is relative to the bottom of the screen (excluding the scrollbar)
+ // and not the bottom of the html element
+ if (offsetParent.nodeName === 'HTML') {
+ top = -offsetParent.clientHeight + offsets.bottom;
+ } else {
+ top = -offsetParentRect.height + offsets.bottom;
}
+ } else {
+ top = offsets.top;
+ }
+ if (sideB === 'right') {
+ if (offsetParent.nodeName === 'HTML') {
+ left = -offsetParent.clientWidth + offsets.right;
+ } else {
+ left = -offsetParentRect.width + offsets.right;
+ }
+ } else {
+ left = offsets.left;
+ }
+ if (gpuAcceleration && prefixedProperty) {
+ styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
+ styles[sideA] = 0;
+ styles[sideB] = 0;
+ styles.willChange = 'transform';
+ } else {
+ // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
+ var invertTop = sideA === 'bottom' ? -1 : 1;
+ var invertLeft = sideB === 'right' ? -1 : 1;
+ styles[sideA] = top * invertTop;
+ styles[sideB] = left * invertLeft;
+ styles.willChange = sideA + ', ' + sideB;
+ }
- var commonStyles = {
- placement: getBasePlacement(state.placement),
- popper: state.elements.popper,
- popperRect: state.rects.popper,
- gpuAcceleration: gpuAcceleration
- };
+ // Attributes
+ var attributes = {
+ 'x-placement': data.placement
+ };
- if (state.modifiersData.popperOffsets != null) {
- state.styles.popper = Object.assign(Object.assign({}, state.styles.popper), mapToStyles(Object.assign(Object.assign({}, commonStyles), {}, {
- offsets: state.modifiersData.popperOffsets,
- position: state.options.strategy,
- adaptive: adaptive
- })));
- }
+ // Update `data` attributes, styles and arrowStyles
+ data.attributes = _extends({}, attributes, data.attributes);
+ data.styles = _extends({}, styles, data.styles);
+ data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
- if (state.modifiersData.arrow != null) {
- state.styles.arrow = Object.assign(Object.assign({}, state.styles.arrow), mapToStyles(Object.assign(Object.assign({}, commonStyles), {}, {
- offsets: state.modifiersData.arrow,
- position: 'absolute',
- adaptive: false
- })));
- }
+ return data;
+}
- state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
- 'data-popper-placement': state.placement
- });
- } // eslint-disable-next-line import/no-unused-modules
+/**
+ * Helper used to know if the given modifier depends from another one.
+ * It checks if the needed modifier is listed and enabled.
+ * @method
+ * @memberof Popper.Utils
+ * @param {Array} modifiers - list of modifiers
+ * @param {String} requestingName - name of requesting modifier
+ * @param {String} requestedName - name of requested modifier
+ * @returns {Boolean}
+ */
+function isModifierRequired(modifiers, requestingName, requestedName) {
+ var requesting = find(modifiers, function (_ref) {
+ var name = _ref.name;
+ return name === requestingName;
+ });
+
+ var isRequired = !!requesting && modifiers.some(function (modifier) {
+ return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
+ });
+
+ if (!isRequired) {
+ var _requesting = '`' + requestingName + '`';
+ var requested = '`' + requestedName + '`';
+ console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
+ }
+ return isRequired;
+}
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function arrow(data, options) {
+ var _data$offsets$arrow;
- var computeStyles$1 = {
- name: 'computeStyles',
- enabled: true,
- phase: 'beforeWrite',
- fn: computeStyles,
- data: {}
- };
+ // arrow depends on keepTogether in order to work
+ if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
+ return data;
+ }
+
+ var arrowElement = options.element;
+
+ // if arrowElement is a string, suppose it's a CSS selector
+ if (typeof arrowElement === 'string') {
+ arrowElement = data.instance.popper.querySelector(arrowElement);
- // and applies them to the HTMLElements such as popper and arrow
+ // if arrowElement is not found, don't run the modifier
+ if (!arrowElement) {
+ return data;
+ }
+ } else {
+ // if the arrowElement isn't a query selector we must check that the
+ // provided DOM node is child of its popper node
+ if (!data.instance.popper.contains(arrowElement)) {
+ console.warn('WARNING: `arrow.element` must be child of its popper element!');
+ return data;
+ }
+ }
- function applyStyles(_ref) {
- var state = _ref.state;
- Object.keys(state.elements).forEach(function (name) {
- var style = state.styles[name] || {};
- var attributes = state.attributes[name] || {};
- var element = state.elements[name]; // arrow is optional + virtual elements
+ var placement = data.placement.split('-')[0];
+ var _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
- if (!isHTMLElement(element) || !getNodeName(element)) {
- return;
- } // Flow doesn't support to extend this property, but it's the most
- // effective way to apply styles to an HTMLElement
- // $FlowFixMe
+ var isVertical = ['left', 'right'].indexOf(placement) !== -1;
+ var len = isVertical ? 'height' : 'width';
+ var sideCapitalized = isVertical ? 'Top' : 'Left';
+ var side = sideCapitalized.toLowerCase();
+ var altSide = isVertical ? 'left' : 'top';
+ var opSide = isVertical ? 'bottom' : 'right';
+ var arrowElementSize = getOuterSizes(arrowElement)[len];
- Object.assign(element.style, style);
- Object.keys(attributes).forEach(function (name) {
- var value = attributes[name];
+ //
+ // extends keepTogether behavior making sure the popper and its
+ // reference have enough pixels in conjunction
+ //
- if (value === false) {
- element.removeAttribute(name);
- } else {
- element.setAttribute(name, value === true ? '' : value);
- }
- });
- });
+ // top/left side
+ if (reference[opSide] - arrowElementSize < popper[side]) {
+ data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
}
+ // bottom/right side
+ if (reference[side] + arrowElementSize > popper[opSide]) {
+ data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
+ }
+ data.offsets.popper = getClientRect(data.offsets.popper);
- function effect$1(_ref2) {
- var state = _ref2.state;
- var initialStyles = {
- popper: {
- position: state.options.strategy,
- left: '0',
- top: '0',
- margin: '0'
- },
- arrow: {
- position: 'absolute'
- },
- reference: {}
- };
- Object.assign(state.elements.popper.style, initialStyles.popper);
+ // compute center of the popper
+ var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
- if (state.elements.arrow) {
- Object.assign(state.elements.arrow.style, initialStyles.arrow);
- }
+ // Compute the sideValue using the updated popper offsets
+ // take popper margin in account because we don't have this info available
+ var css = getStyleComputedProperty(data.instance.popper);
+ var popperMarginSide = parseFloat(css['margin' + sideCapitalized]);
+ var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);
+ var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
- return function () {
- Object.keys(state.elements).forEach(function (name) {
- var element = state.elements[name];
- var attributes = state.attributes[name] || {};
- var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them
-
- var style = styleProperties.reduce(function (style, property) {
- style[property] = '';
- return style;
- }, {}); // arrow is optional + virtual elements
-
- if (!isHTMLElement(element) || !getNodeName(element)) {
- return;
- } // Flow doesn't support to extend this property, but it's the most
- // effective way to apply styles to an HTMLElement
- // $FlowFixMe
-
-
- Object.assign(element.style, style);
- Object.keys(attributes).forEach(function (attribute) {
- element.removeAttribute(attribute);
- });
- });
- };
- } // eslint-disable-next-line import/no-unused-modules
+ // prevent arrowElement from being placed not contiguously to its popper
+ sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
+ data.arrowElement = arrowElement;
+ data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
- var applyStyles$1 = {
- name: 'applyStyles',
- enabled: true,
- phase: 'write',
- fn: applyStyles,
- effect: effect$1,
- requires: ['computeStyles']
- };
+ return data;
+}
- function distanceAndSkiddingToXY(placement, rects, offset) {
- var basePlacement = getBasePlacement(placement);
- var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;
-
- var _ref = typeof offset === 'function' ? offset(Object.assign(Object.assign({}, rects), {}, {
- placement: placement
- })) : offset,
- skidding = _ref[0],
- distance = _ref[1];
-
- skidding = skidding || 0;
- distance = (distance || 0) * invertDistance;
- return [left, right].indexOf(basePlacement) >= 0 ? {
- x: distance,
- y: skidding
- } : {
- x: skidding,
- y: distance
- };
+/**
+ * Get the opposite placement variation of the given one
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement variation
+ * @returns {String} flipped placement variation
+ */
+function getOppositeVariation(variation) {
+ if (variation === 'end') {
+ return 'start';
+ } else if (variation === 'start') {
+ return 'end';
}
+ return variation;
+}
- function offset(_ref2) {
- var state = _ref2.state,
- options = _ref2.options,
- name = _ref2.name;
- var _options$offset = options.offset,
- offset = _options$offset === void 0 ? [0, 0] : _options$offset;
- var data = placements.reduce(function (acc, placement) {
- acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);
- return acc;
- }, {});
- var _data$state$placement = data[state.placement],
- x = _data$state$placement.x,
- y = _data$state$placement.y;
-
- if (state.modifiersData.popperOffsets != null) {
- state.modifiersData.popperOffsets.x += x;
- state.modifiersData.popperOffsets.y += y;
- }
+/**
+ * List of accepted placements to use as values of the `placement` option.
+ * Valid placements are:
+ * - `auto`
+ * - `top`
+ * - `right`
+ * - `bottom`
+ * - `left`
+ *
+ * Each placement can have a variation from this list:
+ * - `-start`
+ * - `-end`
+ *
+ * Variations are interpreted easily if you think of them as the left to right
+ * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
+ * is right.
+ * Vertically (`left` and `right`), `start` is top and `end` is bottom.
+ *
+ * Some valid examples are:
+ * - `top-end` (on top of reference, right aligned)
+ * - `right-start` (on right of reference, top aligned)
+ * - `bottom` (on bottom, centered)
+ * - `auto-end` (on the side with more space available, alignment depends by placement)
+ *
+ * @static
+ * @type {Array}
+ * @enum {String}
+ * @readonly
+ * @method placements
+ * @memberof Popper
+ */
+var 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'];
- state.modifiersData[name] = data;
- } // eslint-disable-next-line import/no-unused-modules
+// Get rid of `auto` `auto-start` and `auto-end`
+var validPlacements = placements.slice(3);
+/**
+ * Given an initial placement, returns all the subsequent placements
+ * clockwise (or counter-clockwise).
+ *
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement - A valid placement (it accepts variations)
+ * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
+ * @returns {Array} placements including their variations
+ */
+function clockwise(placement) {
+ var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- var offset$1 = {
- name: 'offset',
- enabled: true,
- phase: 'main',
- requires: ['popperOffsets'],
- fn: offset
- };
+ var index = validPlacements.indexOf(placement);
+ var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
+ return counter ? arr.reverse() : arr;
+}
- var hash = {
- left: 'right',
- right: 'left',
- bottom: 'top',
- top: 'bottom'
- };
- function getOppositePlacement(placement) {
- return placement.replace(/left|right|bottom|top/g, function (matched) {
- return hash[matched];
- });
+var BEHAVIORS = {
+ FLIP: 'flip',
+ CLOCKWISE: 'clockwise',
+ COUNTERCLOCKWISE: 'counterclockwise'
+};
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function flip(data, options) {
+ // if `inner` modifier is enabled, we can't use the `flip` modifier
+ if (isModifierEnabled(data.instance.modifiers, 'inner')) {
+ return data;
}
- var hash$1 = {
- start: 'end',
- end: 'start'
- };
- function getOppositeVariationPlacement(placement) {
- return placement.replace(/start|end/g, function (matched) {
- return hash$1[matched];
- });
+ if (data.flipped && data.placement === data.originalPlacement) {
+ // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
+ return data;
}
- /*:: type OverflowsMap = { [ComputedPlacement]: number }; */
+ var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
+
+ var placement = data.placement.split('-')[0];
+ var placementOpposite = getOppositePlacement(placement);
+ var variation = data.placement.split('-')[1] || '';
+
+ var flipOrder = [];
+
+ switch (options.behavior) {
+ case BEHAVIORS.FLIP:
+ flipOrder = [placement, placementOpposite];
+ break;
+ case BEHAVIORS.CLOCKWISE:
+ flipOrder = clockwise(placement);
+ break;
+ case BEHAVIORS.COUNTERCLOCKWISE:
+ flipOrder = clockwise(placement, true);
+ break;
+ default:
+ flipOrder = options.behavior;
+ }
- /*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */
- function computeAutoPlacement(state, options) {
- if (options === void 0) {
- options = {};
+ flipOrder.forEach(function (step, index) {
+ if (placement !== step || flipOrder.length === index + 1) {
+ return data;
}
- var _options = options,
- placement = _options.placement,
- boundary = _options.boundary,
- rootBoundary = _options.rootBoundary,
- padding = _options.padding,
- flipVariations = _options.flipVariations,
- _options$allowedAutoP = _options.allowedAutoPlacements,
- allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
- var variation = getVariation(placement);
- var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {
- return getVariation(placement) === variation;
- }) : basePlacements; // $FlowFixMe
-
- var allowedPlacements = placements$1.filter(function (placement) {
- return allowedAutoPlacements.indexOf(placement) >= 0;
- });
+ placement = data.placement.split('-')[0];
+ placementOpposite = getOppositePlacement(placement);
- if (allowedPlacements.length === 0) {
- allowedPlacements = placements$1;
+ var popperOffsets = data.offsets.popper;
+ var refOffsets = data.offsets.reference;
- {
- console.error(['Popper: The `allowedAutoPlacements` option did not allow any', 'placements. Ensure the `placement` option matches the variation', 'of the allowed placements.', 'For example, "auto" cannot be used to allow "bottom-start".', 'Use "auto-start" instead.'].join(' '));
- }
- } // $FlowFixMe: Flow seems to have problems with two array unions...
-
-
- var overflows = allowedPlacements.reduce(function (acc, placement) {
- acc[placement] = detectOverflow(state, {
- placement: placement,
- boundary: boundary,
- rootBoundary: rootBoundary,
- padding: padding
- })[getBasePlacement(placement)];
- return acc;
- }, {});
- return Object.keys(overflows).sort(function (a, b) {
- return overflows[a] - overflows[b];
- });
- }
+ // using floor because the reference offsets may contain decimals we are not going to consider here
+ var floor = Math.floor;
+ var 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);
- function getExpandedFallbackPlacements(placement) {
- if (getBasePlacement(placement) === auto) {
- return [];
- }
+ var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
+ var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
+ var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
+ var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
- var oppositePlacement = getOppositePlacement(placement);
- return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
- }
+ var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
- function flip(_ref) {
- var state = _ref.state,
- options = _ref.options,
- name = _ref.name;
+ // flip the variation if required
+ var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
- if (state.modifiersData[name]._skip) {
- return;
- }
+ // flips variation if reference element overflows boundaries
+ var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
- var _options$mainAxis = options.mainAxis,
- checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
- _options$altAxis = options.altAxis,
- checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,
- specifiedFallbackPlacements = options.fallbackPlacements,
- padding = options.padding,
- boundary = options.boundary,
- rootBoundary = options.rootBoundary,
- altBoundary = options.altBoundary,
- _options$flipVariatio = options.flipVariations,
- flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,
- allowedAutoPlacements = options.allowedAutoPlacements;
- var preferredPlacement = state.options.placement;
- var basePlacement = getBasePlacement(preferredPlacement);
- var isBasePlacement = basePlacement === preferredPlacement;
- var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
- var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {
- return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {
- placement: placement,
- boundary: boundary,
- rootBoundary: rootBoundary,
- padding: padding,
- flipVariations: flipVariations,
- allowedAutoPlacements: allowedAutoPlacements
- }) : placement);
- }, []);
- var referenceRect = state.rects.reference;
- var popperRect = state.rects.popper;
- var checksMap = new Map();
- var makeFallbackChecks = true;
- var firstFittingPlacement = placements[0];
-
- for (var i = 0; i < placements.length; i++) {
- var placement = placements[i];
-
- var _basePlacement = getBasePlacement(placement);
-
- var isStartVariation = getVariation(placement) === start;
- var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
- var len = isVertical ? 'width' : 'height';
- var overflow = detectOverflow(state, {
- placement: placement,
- boundary: boundary,
- rootBoundary: rootBoundary,
- altBoundary: altBoundary,
- padding: padding
- });
- var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
-
- if (referenceRect[len] > popperRect[len]) {
- mainVariationSide = getOppositePlacement(mainVariationSide);
- }
+ // flips variation if popper content overflows boundaries
+ var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
- var altVariationSide = getOppositePlacement(mainVariationSide);
- var checks = [];
+ var flippedVariation = flippedVariationByRef || flippedVariationByContent;
- if (checkMainAxis) {
- checks.push(overflow[_basePlacement] <= 0);
- }
+ if (overlapsRef || overflowsBoundaries || flippedVariation) {
+ // this boolean to detect any flip loop
+ data.flipped = true;
- if (checkAltAxis) {
- checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
+ if (overlapsRef || overflowsBoundaries) {
+ placement = flipOrder[index + 1];
}
- if (checks.every(function (check) {
- return check;
- })) {
- firstFittingPlacement = placement;
- makeFallbackChecks = false;
- break;
+ if (flippedVariation) {
+ variation = getOppositeVariation(variation);
}
- checksMap.set(placement, checks);
- }
+ data.placement = placement + (variation ? '-' + variation : '');
- if (makeFallbackChecks) {
- // `2` may be desired in some cases – research later
- var numberOfChecks = flipVariations ? 3 : 1;
+ // this object contains `position`, we want to preserve it along with
+ // any additional property we may add in the future
+ data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
- var _loop = function _loop(_i) {
- var fittingPlacement = placements.find(function (placement) {
- var checks = checksMap.get(placement);
+ data = runModifiers(data.instance.modifiers, data, 'flip');
+ }
+ });
+ return data;
+}
- if (checks) {
- return checks.slice(0, _i).every(function (check) {
- return check;
- });
- }
- });
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function keepTogether(data) {
+ var _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
+
+ var placement = data.placement.split('-')[0];
+ var floor = Math.floor;
+ var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
+ var side = isVertical ? 'right' : 'bottom';
+ var opSide = isVertical ? 'left' : 'top';
+ var measurement = isVertical ? 'width' : 'height';
+
+ if (popper[side] < floor(reference[opSide])) {
+ data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
+ }
+ if (popper[opSide] > floor(reference[side])) {
+ data.offsets.popper[opSide] = floor(reference[side]);
+ }
- if (fittingPlacement) {
- firstFittingPlacement = fittingPlacement;
- return "break";
- }
- };
+ return data;
+}
- for (var _i = numberOfChecks; _i > 0; _i--) {
- var _ret = _loop(_i);
+/**
+ * Converts a string containing value + unit into a px value number
+ * @function
+ * @memberof {modifiers~offset}
+ * @private
+ * @argument {String} str - Value + unit string
+ * @argument {String} measurement - `height` or `width`
+ * @argument {Object} popperOffsets
+ * @argument {Object} referenceOffsets
+ * @returns {Number|String}
+ * Value in pixels, or original string if no values were extracted
+ */
+function toValue(str, measurement, popperOffsets, referenceOffsets) {
+ // separate value from unit
+ var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
+ var value = +split[1];
+ var unit = split[2];
+
+ // If it's not a number it's an operator, I guess
+ if (!value) {
+ return str;
+ }
- if (_ret === "break") break;
- }
+ if (unit.indexOf('%') === 0) {
+ var element = void 0;
+ switch (unit) {
+ case '%p':
+ element = popperOffsets;
+ break;
+ case '%':
+ case '%r':
+ default:
+ element = referenceOffsets;
}
- if (state.placement !== firstFittingPlacement) {
- state.modifiersData[name]._skip = true;
- state.placement = firstFittingPlacement;
- state.reset = true;
+ var rect = getClientRect(element);
+ return rect[measurement] / 100 * value;
+ } else if (unit === 'vh' || unit === 'vw') {
+ // if is a vh or vw, we calculate the size based on the viewport
+ var size = void 0;
+ if (unit === 'vh') {
+ size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
+ } else {
+ size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
}
- } // eslint-disable-next-line import/no-unused-modules
+ return size / 100 * value;
+ } else {
+ // if is an explicit pixel unit, we get rid of the unit and keep the value
+ // if is an implicit unit, it's px, and we return just the value
+ return value;
+ }
+}
+/**
+ * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
+ * @function
+ * @memberof {modifiers~offset}
+ * @private
+ * @argument {String} offset
+ * @argument {Object} popperOffsets
+ * @argument {Object} referenceOffsets
+ * @argument {String} basePlacement
+ * @returns {Array} a two cells array with x and y offsets in numbers
+ */
+function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
+ var offsets = [0, 0];
+
+ // Use height if placement is left or right and index is 0 otherwise use width
+ // in this way the first offset will use an axis and the second one
+ // will use the other one
+ var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
+
+ // Split the offset string to obtain a list of values and operands
+ // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
+ var fragments = offset.split(/(\+|\-)/).map(function (frag) {
+ return frag.trim();
+ });
+
+ // Detect if the offset string contains a pair of values or a single one
+ // they could be separated by comma or space
+ var divider = fragments.indexOf(find(fragments, function (frag) {
+ return frag.search(/,|\s/) !== -1;
+ }));
+
+ if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
+ console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
+ }
- var flip$1 = {
- name: 'flip',
- enabled: true,
- phase: 'main',
- fn: flip,
- requiresIfExists: ['offset'],
- data: {
- _skip: false
+ // If divider is found, we divide the list of values and operands to divide
+ // them by ofset X and Y.
+ var splitRegex = /\s*,\s*|\s+/;
+ var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
+
+ // Convert the values with units to absolute pixels to allow our computations
+ ops = ops.map(function (op, index) {
+ // Most of the units rely on the orientation of the popper
+ var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
+ var mergeWithPrevious = false;
+ return op
+ // This aggregates any `+` or `-` sign that aren't considered operators
+ // e.g.: 10 + +5 => [10, +, +5]
+ .reduce(function (a, b) {
+ if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
+ a[a.length - 1] = b;
+ mergeWithPrevious = true;
+ return a;
+ } else if (mergeWithPrevious) {
+ a[a.length - 1] += b;
+ mergeWithPrevious = false;
+ return a;
+ } else {
+ return a.concat(b);
+ }
+ }, [])
+ // Here we convert the string values into number values (in px)
+ .map(function (str) {
+ return toValue(str, measurement, popperOffsets, referenceOffsets);
+ });
+ });
+
+ // Loop trough the offsets arrays and execute the operations
+ ops.forEach(function (op, index) {
+ op.forEach(function (frag, index2) {
+ if (isNumeric(frag)) {
+ offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
+ }
+ });
+ });
+ return offsets;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @argument {Number|String} options.offset=0
+ * The offset value as described in the modifier description
+ * @returns {Object} The data object, properly modified
+ */
+function offset(data, _ref) {
+ var offset = _ref.offset;
+ var placement = data.placement,
+ _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
+
+ var basePlacement = placement.split('-')[0];
+
+ var offsets = void 0;
+ if (isNumeric(+offset)) {
+ offsets = [+offset, 0];
+ } else {
+ offsets = parseOffset(offset, popper, reference, basePlacement);
+ }
+
+ if (basePlacement === 'left') {
+ popper.top += offsets[0];
+ popper.left -= offsets[1];
+ } else if (basePlacement === 'right') {
+ popper.top += offsets[0];
+ popper.left += offsets[1];
+ } else if (basePlacement === 'top') {
+ popper.left += offsets[0];
+ popper.top -= offsets[1];
+ } else if (basePlacement === 'bottom') {
+ popper.left += offsets[0];
+ popper.top += offsets[1];
+ }
+
+ data.popper = popper;
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function preventOverflow(data, options) {
+ var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
+
+ // If offsetParent is the reference element, we really want to
+ // go one step up and use the next offsetParent as reference to
+ // avoid to make this modifier completely useless and look like broken
+ if (data.instance.reference === boundariesElement) {
+ boundariesElement = getOffsetParent(boundariesElement);
+ }
+
+ // NOTE: DOM access here
+ // resets the popper's position so that the document size can be calculated excluding
+ // the size of the popper element itself
+ var transformProp = getSupportedPropertyName('transform');
+ var popperStyles = data.instance.popper.style; // assignment to help minification
+ var top = popperStyles.top,
+ left = popperStyles.left,
+ transform = popperStyles[transformProp];
+
+ popperStyles.top = '';
+ popperStyles.left = '';
+ popperStyles[transformProp] = '';
+
+ var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
+
+ // NOTE: DOM access here
+ // restores the original style properties after the offsets have been computed
+ popperStyles.top = top;
+ popperStyles.left = left;
+ popperStyles[transformProp] = transform;
+
+ options.boundaries = boundaries;
+
+ var order = options.priority;
+ var popper = data.offsets.popper;
+
+ var check = {
+ primary: function primary(placement) {
+ var value = popper[placement];
+ if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
+ value = Math.max(popper[placement], boundaries[placement]);
+ }
+ return defineProperty({}, placement, value);
+ },
+ secondary: function secondary(placement) {
+ var mainSide = placement === 'right' ? 'left' : 'top';
+ var value = popper[mainSide];
+ if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
+ value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
+ }
+ return defineProperty({}, mainSide, value);
}
};
- function getAltAxis(axis) {
- return axis === 'x' ? 'y' : 'x';
- }
-
- function within(min, value, max) {
- return Math.max(min, Math.min(value, max));
- }
-
- function preventOverflow(_ref) {
- var state = _ref.state,
- options = _ref.options,
- name = _ref.name;
- var _options$mainAxis = options.mainAxis,
- checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
- _options$altAxis = options.altAxis,
- checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,
- boundary = options.boundary,
- rootBoundary = options.rootBoundary,
- altBoundary = options.altBoundary,
- padding = options.padding,
- _options$tether = options.tether,
- tether = _options$tether === void 0 ? true : _options$tether,
- _options$tetherOffset = options.tetherOffset,
- tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
- var overflow = detectOverflow(state, {
- boundary: boundary,
- rootBoundary: rootBoundary,
- padding: padding,
- altBoundary: altBoundary
- });
- var basePlacement = getBasePlacement(state.placement);
- var variation = getVariation(state.placement);
- var isBasePlacement = !variation;
- var mainAxis = getMainAxisFromPlacement(basePlacement);
- var altAxis = getAltAxis(mainAxis);
- var popperOffsets = state.modifiersData.popperOffsets;
- var referenceRect = state.rects.reference;
- var popperRect = state.rects.popper;
- var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign(Object.assign({}, state.rects), {}, {
- placement: state.placement
- })) : tetherOffset;
- var data = {
- x: 0,
- y: 0
+ order.forEach(function (placement) {
+ var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
+ popper = _extends({}, popper, check[side](placement));
+ });
+
+ data.offsets.popper = popper;
+
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function shift(data) {
+ var placement = data.placement;
+ var basePlacement = placement.split('-')[0];
+ var shiftvariation = placement.split('-')[1];
+
+ // if shift shiftvariation is specified, run the modifier
+ if (shiftvariation) {
+ var _data$offsets = data.offsets,
+ reference = _data$offsets.reference,
+ popper = _data$offsets.popper;
+
+ var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
+ var side = isVertical ? 'left' : 'top';
+ var measurement = isVertical ? 'width' : 'height';
+
+ var shiftOffsets = {
+ start: defineProperty({}, side, reference[side]),
+ end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
};
- if (!popperOffsets) {
- return;
+ data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
+ }
+
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function hide(data) {
+ if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
+ return data;
+ }
+
+ var refRect = data.offsets.reference;
+ var bound = find(data.instance.modifiers, function (modifier) {
+ return modifier.name === 'preventOverflow';
+ }).boundaries;
+
+ if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
+ // Avoid unnecessary DOM access if visibility hasn't changed
+ if (data.hide === true) {
+ return data;
}
- if (checkMainAxis) {
- var mainSide = mainAxis === 'y' ? top : left;
- var altSide = mainAxis === 'y' ? bottom : right;
- var len = mainAxis === 'y' ? 'height' : 'width';
- var offset = popperOffsets[mainAxis];
- var min = popperOffsets[mainAxis] + overflow[mainSide];
- var max = popperOffsets[mainAxis] - overflow[altSide];
- var additive = tether ? -popperRect[len] / 2 : 0;
- var minLen = variation === start ? referenceRect[len] : popperRect[len];
- var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go
- // outside the reference bounds
-
- var arrowElement = state.elements.arrow;
- var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
- width: 0,
- height: 0
- };
- var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();
- var arrowPaddingMin = arrowPaddingObject[mainSide];
- var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want
- // to include its full size in the calculation. If the reference is small
- // and near the edge of a boundary, the popper can overflow even if the
- // reference is not overflowing as well (e.g. virtual elements with no
- // width or height)
-
- var arrowLen = within(0, referenceRect[len], arrowRect[len]);
- var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - tetherOffsetValue : minLen - arrowLen - arrowPaddingMin - tetherOffsetValue;
- var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + tetherOffsetValue : maxLen + arrowLen + arrowPaddingMax + tetherOffsetValue;
- var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
- var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
- var offsetModifierValue = state.modifiersData.offset ? state.modifiersData.offset[state.placement][mainAxis] : 0;
- var tetherMin = popperOffsets[mainAxis] + minOffset - offsetModifierValue - clientOffset;
- var tetherMax = popperOffsets[mainAxis] + maxOffset - offsetModifierValue;
- var preventedOffset = within(tether ? Math.min(min, tetherMin) : min, offset, tether ? Math.max(max, tetherMax) : max);
- popperOffsets[mainAxis] = preventedOffset;
- data[mainAxis] = preventedOffset - offset;
+ data.hide = true;
+ data.attributes['x-out-of-boundaries'] = '';
+ } else {
+ // Avoid unnecessary DOM access if visibility hasn't changed
+ if (data.hide === false) {
+ return data;
}
- if (checkAltAxis) {
- var _mainSide = mainAxis === 'x' ? top : left;
+ data.hide = false;
+ data.attributes['x-out-of-boundaries'] = false;
+ }
- var _altSide = mainAxis === 'x' ? bottom : right;
+ return data;
+}
- var _offset = popperOffsets[altAxis];
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function inner(data) {
+ var placement = data.placement;
+ var basePlacement = placement.split('-')[0];
+ var _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
- var _min = _offset + overflow[_mainSide];
+ var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
- var _max = _offset - overflow[_altSide];
+ var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
- var _preventedOffset = within(_min, _offset, _max);
+ popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
- popperOffsets[altAxis] = _preventedOffset;
- data[altAxis] = _preventedOffset - _offset;
- }
+ data.placement = getOppositePlacement(placement);
+ data.offsets.popper = getClientRect(popper);
- state.modifiersData[name] = data;
- } // eslint-disable-next-line import/no-unused-modules
+ return data;
+}
+/**
+ * Modifier function, each modifier can have a function of this type assigned
+ * to its `fn` property.
+ * These functions will be called on each update, this means that you must
+ * make sure they are performant enough to avoid performance bottlenecks.
+ *
+ * @function ModifierFn
+ * @argument {dataObject} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {dataObject} The data object, properly modified
+ */
- var preventOverflow$1 = {
- name: 'preventOverflow',
+/**
+ * Modifiers are plugins used to alter the behavior of your poppers.
+ * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
+ * needed by the library.
+ *
+ * Usually you don't want to override the `order`, `fn` and `onLoad` props.
+ * All the other properties are configurations that could be tweaked.
+ * @namespace modifiers
+ */
+var modifiers = {
+ /**
+ * Modifier used to shift the popper on the start or end of its reference
+ * element.
+ * It will read the variation of the `placement` property.
+ * It can be one either `-end` or `-start`.
+ * @memberof modifiers
+ * @inner
+ */
+ shift: {
+ /** @prop {number} order=100 - Index used to define the order of execution */
+ order: 100,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: shift
+ },
+
+ /**
+ * The `offset` modifier can shift your popper on both its axis.
+ *
+ * It accepts the following units:
+ * - `px` or unit-less, interpreted as pixels
+ * - `%` or `%r`, percentage relative to the length of the reference element
+ * - `%p`, percentage relative to the length of the popper element
+ * - `vw`, CSS viewport width unit
+ * - `vh`, CSS viewport height unit
+ *
+ * For length is intended the main axis relative to the placement of the popper.
+ * This means that if the placement is `top` or `bottom`, the length will be the
+ * `width`. In case of `left` or `right`, it will be the `height`.
+ *
+ * You can provide a single value (as `Number` or `String`), or a pair of values
+ * as `String` divided by a comma or one (or more) white spaces.
+ * The latter is a deprecated method because it leads to confusion and will be
+ * removed in v2.
+ * Additionally, it accepts additions and subtractions between different units.
+ * Note that multiplications and divisions aren't supported.
+ *
+ * Valid examples are:
+ * ```
+ * 10
+ * '10%'
+ * '10, 10'
+ * '10%, 10'
+ * '10 + 10%'
+ * '10 - 5vh + 3%'
+ * '-10px + 5vh, 5px - 6%'
+ * ```
+ * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
+ * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
+ * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ offset: {
+ /** @prop {number} order=200 - Index used to define the order of execution */
+ order: 200,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: offset,
+ /** @prop {Number|String} offset=0
+ * The offset value as described in the modifier description
+ */
+ offset: 0
+ },
+
+ /**
+ * Modifier used to prevent the popper from being positioned outside the boundary.
+ *
+ * A scenario exists where the reference itself is not within the boundaries.
+ * We can say it has "escaped the boundaries" — or just "escaped".
+ * In this case we need to decide whether the popper should either:
+ *
+ * - detach from the reference and remain "trapped" in the boundaries, or
+ * - if it should ignore the boundary and "escape with its reference"
+ *
+ * When `escapeWithReference` is set to`true` and reference is completely
+ * outside its boundaries, the popper will overflow (or completely leave)
+ * the boundaries in order to remain attached to the edge of the reference.
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ preventOverflow: {
+ /** @prop {number} order=300 - Index used to define the order of execution */
+ order: 300,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
- phase: 'main',
+ /** @prop {ModifierFn} */
fn: preventOverflow,
- requiresIfExists: ['offset']
- };
+ /**
+ * @prop {Array} [priority=['left','right','top','bottom']]
+ * Popper will try to prevent overflow following these priorities by default,
+ * then, it could overflow on the left and on top of the `boundariesElement`
+ */
+ priority: ['left', 'right', 'top', 'bottom'],
+ /**
+ * @prop {number} padding=5
+ * Amount of pixel used to define a minimum distance between the boundaries
+ * and the popper. This makes sure the popper always has a little padding
+ * between the edges of its container
+ */
+ padding: 5,
+ /**
+ * @prop {String|HTMLElement} boundariesElement='scrollParent'
+ * Boundaries used by the modifier. Can be `scrollParent`, `window`,
+ * `viewport` or any DOM element.
+ */
+ boundariesElement: 'scrollParent'
+ },
+
+ /**
+ * Modifier used to make sure the reference and its popper stay near each other
+ * without leaving any gap between the two. Especially useful when the arrow is
+ * enabled and you want to ensure that it points to its reference element.
+ * It cares only about the first axis. You can still have poppers with margin
+ * between the popper and its reference element.
+ * @memberof modifiers
+ * @inner
+ */
+ keepTogether: {
+ /** @prop {number} order=400 - Index used to define the order of execution */
+ order: 400,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: keepTogether
+ },
+
+ /**
+ * This modifier is used to move the `arrowElement` of the popper to make
+ * sure it is positioned between the reference element and its popper element.
+ * It will read the outer size of the `arrowElement` node to detect how many
+ * pixels of conjunction are needed.
+ *
+ * It has no effect if no `arrowElement` is provided.
+ * @memberof modifiers
+ * @inner
+ */
+ arrow: {
+ /** @prop {number} order=500 - Index used to define the order of execution */
+ order: 500,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: arrow,
+ /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
+ element: '[x-arrow]'
+ },
+
+ /**
+ * Modifier used to flip the popper's placement when it starts to overlap its
+ * reference element.
+ *
+ * Requires the `preventOverflow` modifier before it in order to work.
+ *
+ * **NOTE:** this modifier will interrupt the current update cycle and will
+ * restart it if it detects the need to flip the placement.
+ * @memberof modifiers
+ * @inner
+ */
+ flip: {
+ /** @prop {number} order=600 - Index used to define the order of execution */
+ order: 600,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: flip,
+ /**
+ * @prop {String|Array} behavior='flip'
+ * The behavior used to change the popper's placement. It can be one of
+ * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
+ * placements (with optional variations)
+ */
+ behavior: 'flip',
+ /**
+ * @prop {number} padding=5
+ * The popper will flip if it hits the edges of the `boundariesElement`
+ */
+ padding: 5,
+ /**
+ * @prop {String|HTMLElement} boundariesElement='viewport'
+ * The element which will define the boundaries of the popper position.
+ * The popper will never be placed outside of the defined boundaries
+ * (except if `keepTogether` is enabled)
+ */
+ boundariesElement: 'viewport',
+ /**
+ * @prop {Boolean} flipVariations=false
+ * The popper will switch placement variation between `-start` and `-end` when
+ * the reference element overlaps its boundaries.
+ *
+ * The original placement should have a set variation.
+ */
+ flipVariations: false,
+ /**
+ * @prop {Boolean} flipVariationsByContent=false
+ * The popper will switch placement variation between `-start` and `-end` when
+ * the popper element overlaps its reference boundaries.
+ *
+ * The original placement should have a set variation.
+ */
+ flipVariationsByContent: false
+ },
+
+ /**
+ * Modifier used to make the popper flow toward the inner of the reference element.
+ * By default, when this modifier is disabled, the popper will be placed outside
+ * the reference element.
+ * @memberof modifiers
+ * @inner
+ */
+ inner: {
+ /** @prop {number} order=700 - Index used to define the order of execution */
+ order: 700,
+ /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
+ enabled: false,
+ /** @prop {ModifierFn} */
+ fn: inner
+ },
+
+ /**
+ * Modifier used to hide the popper when its reference element is outside of the
+ * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
+ * be used to hide with a CSS selector the popper when its reference is
+ * out of boundaries.
+ *
+ * Requires the `preventOverflow` modifier before it in order to work.
+ * @memberof modifiers
+ * @inner
+ */
+ hide: {
+ /** @prop {number} order=800 - Index used to define the order of execution */
+ order: 800,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: hide
+ },
+
+ /**
+ * Computes the style that will be applied to the popper element to gets
+ * properly positioned.
+ *
+ * Note that this modifier will not touch the DOM, it just prepares the styles
+ * so that `applyStyle` modifier can apply it. This separation is useful
+ * in case you need to replace `applyStyle` with a custom implementation.
+ *
+ * This modifier has `850` as `order` value to maintain backward compatibility
+ * with previous versions of Popper.js. Expect the modifiers ordering method
+ * to change in future major versions of the library.
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ computeStyle: {
+ /** @prop {number} order=850 - Index used to define the order of execution */
+ order: 850,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: computeStyle,
+ /**
+ * @prop {Boolean} gpuAcceleration=true
+ * If true, it uses the CSS 3D transformation to position the popper.
+ * Otherwise, it will use the `top` and `left` properties
+ */
+ gpuAcceleration: true,
+ /**
+ * @prop {string} [x='bottom']
+ * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
+ * Change this if your popper should grow in a direction different from `bottom`
+ */
+ x: 'bottom',
+ /**
+ * @prop {string} [x='left']
+ * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
+ * Change this if your popper should grow in a direction different from `right`
+ */
+ y: 'right'
+ },
+
+ /**
+ * Applies the computed styles to the popper element.
+ *
+ * All the DOM manipulations are limited to this modifier. This is useful in case
+ * you want to integrate Popper.js inside a framework or view library and you
+ * want to delegate all the DOM manipulations to it.
+ *
+ * Note that if you disable this modifier, you must make sure the popper element
+ * has its position set to `absolute` before Popper.js can do its work!
+ *
+ * Just disable this modifier and define your own to achieve the desired effect.
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ applyStyle: {
+ /** @prop {number} order=900 - Index used to define the order of execution */
+ order: 900,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: applyStyle,
+ /** @prop {Function} */
+ onLoad: applyStyleOnLoad,
+ /**
+ * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
+ * @prop {Boolean} gpuAcceleration=true
+ * If true, it uses the CSS 3D transformation to position the popper.
+ * Otherwise, it will use the `top` and `left` properties
+ */
+ gpuAcceleration: undefined
+ }
+};
- function arrow(_ref) {
- var _state$modifiersData$;
+/**
+ * The `dataObject` is an object containing all the information used by Popper.js.
+ * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
+ * @name dataObject
+ * @property {Object} data.instance The Popper.js instance
+ * @property {String} data.placement Placement applied to popper
+ * @property {String} data.originalPlacement Placement originally defined on init
+ * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
+ * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
+ * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
+ * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
+ * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
+ * @property {Object} data.boundaries Offsets of the popper boundaries
+ * @property {Object} data.offsets The measurements of popper, reference and arrow elements
+ * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
+ * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
+ * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
+ */
- var state = _ref.state,
- name = _ref.name;
- var arrowElement = state.elements.arrow;
- var popperOffsets = state.modifiersData.popperOffsets;
- var basePlacement = getBasePlacement(state.placement);
- var axis = getMainAxisFromPlacement(basePlacement);
- var isVertical = [left, right].indexOf(basePlacement) >= 0;
- var len = isVertical ? 'height' : 'width';
+/**
+ * Default options provided to Popper.js constructor.
+ * These can be overridden using the `options` argument of Popper.js.
+ * To override an option, simply pass an object with the same
+ * structure of the `options` object, as the 3rd argument. For example:
+ * ```
+ * new Popper(ref, pop, {
+ * modifiers: {
+ * preventOverflow: { enabled: false }
+ * }
+ * })
+ * ```
+ * @type {Object}
+ * @static
+ * @memberof Popper
+ */
+var Defaults = {
+ /**
+ * Popper's placement.
+ * @prop {Popper.placements} placement='bottom'
+ */
+ placement: 'bottom',
+
+ /**
+ * Set this to true if you want popper to position it self in 'fixed' mode
+ * @prop {Boolean} positionFixed=false
+ */
+ positionFixed: false,
+
+ /**
+ * Whether events (resize, scroll) are initially enabled.
+ * @prop {Boolean} eventsEnabled=true
+ */
+ eventsEnabled: true,
+
+ /**
+ * Set to true if you want to automatically remove the popper when
+ * you call the `destroy` method.
+ * @prop {Boolean} removeOnDestroy=false
+ */
+ removeOnDestroy: false,
+
+ /**
+ * Callback called when the popper is created.
+ * By default, it is set to no-op.
+ * Access Popper.js instance with `data.instance`.
+ * @prop {onCreate}
+ */
+ onCreate: function onCreate() {},
+
+ /**
+ * Callback called when the popper is updated. This callback is not called
+ * on the initialization/creation of the popper, but only on subsequent
+ * updates.
+ * By default, it is set to no-op.
+ * Access Popper.js instance with `data.instance`.
+ * @prop {onUpdate}
+ */
+ onUpdate: function onUpdate() {},
+
+ /**
+ * List of modifiers used to modify the offsets before they are applied to the popper.
+ * They provide most of the functionalities of Popper.js.
+ * @prop {modifiers}
+ */
+ modifiers: modifiers
+};
- if (!arrowElement || !popperOffsets) {
- return;
- }
+/**
+ * @callback onCreate
+ * @param {dataObject} data
+ */
- var paddingObject = state.modifiersData[name + "#persistent"].padding;
- var arrowRect = getLayoutRect(arrowElement);
- var minProp = axis === 'y' ? top : left;
- var maxProp = axis === 'y' ? bottom : right;
- var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
- var startDiff = popperOffsets[axis] - state.rects.reference[axis];
- var arrowOffsetParent = getOffsetParent(arrowElement);
- var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
- var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is
- // outside of the popper bounds
-
- var min = paddingObject[minProp];
- var max = clientSize - arrowRect[len] - paddingObject[maxProp];
- var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
- var offset = within(min, center, max); // Prevents breaking syntax highlighting...
-
- var axisProp = axis;
- state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
- }
-
- function effect$2(_ref2) {
- var state = _ref2.state,
- options = _ref2.options,
- name = _ref2.name;
- var _options$element = options.element,
- arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element,
- _options$padding = options.padding,
- padding = _options$padding === void 0 ? 0 : _options$padding;
-
- if (arrowElement == null) {
- return;
- } // CSS selector
+/**
+ * @callback onUpdate
+ * @param {dataObject} data
+ */
+// Utils
+// Methods
+var Popper = function () {
+ /**
+ * Creates a new Popper.js instance.
+ * @class Popper
+ * @param {Element|referenceObject} reference - The reference element used to position the popper
+ * @param {Element} popper - The HTML / XML element used as the popper
+ * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
+ * @return {Object} instance - The generated Popper.js instance
+ */
+ function Popper(reference, popper) {
+ var _this = this;
+
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+ classCallCheck(this, Popper);
+
+ this.scheduleUpdate = function () {
+ return requestAnimationFrame(_this.update);
+ };
- if (typeof arrowElement === 'string') {
- arrowElement = state.elements.popper.querySelector(arrowElement);
+ // make update() debounced, so that it only runs at most once-per-tick
+ this.update = debounce(this.update.bind(this));
- if (!arrowElement) {
- return;
- }
- }
+ // with {} we create a new object with the options inside it
+ this.options = _extends({}, Popper.Defaults, options);
- {
- if (!isHTMLElement(arrowElement)) {
- console.error(['Popper: "arrow" element must be an HTMLElement (not an SVGElement).', 'To use an SVG arrow, wrap it in an HTMLElement that will be used as', 'the arrow.'].join(' '));
- }
- }
+ // init state
+ this.state = {
+ isDestroyed: false,
+ isCreated: false,
+ scrollParents: []
+ };
- if (!contains(state.elements.popper, arrowElement)) {
- {
- console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', 'element.'].join(' '));
- }
+ // get reference and popper elements (allow jQuery wrappers)
+ this.reference = reference && reference.jquery ? reference[0] : reference;
+ this.popper = popper && popper.jquery ? popper[0] : popper;
- return;
- }
+ // Deep merge modifiers options
+ this.options.modifiers = {};
+ Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
+ _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
+ });
- state.elements.arrow = arrowElement;
- state.modifiersData[name + "#persistent"] = {
- padding: mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements))
- };
- } // eslint-disable-next-line import/no-unused-modules
+ // Refactoring modifiers' list (Object => Array)
+ this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
+ return _extends({
+ name: name
+ }, _this.options.modifiers[name]);
+ })
+ // sort the modifiers by order
+ .sort(function (a, b) {
+ return a.order - b.order;
+ });
+ // modifiers have the ability to execute arbitrary code when Popper.js get inited
+ // such code is executed in the same order of its modifier
+ // they could add new properties to their options configuration
+ // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
+ this.modifiers.forEach(function (modifierOptions) {
+ if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
+ modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
+ }
+ });
- var arrow$1 = {
- name: 'arrow',
- enabled: true,
- phase: 'main',
- fn: arrow,
- effect: effect$2,
- requires: ['popperOffsets'],
- requiresIfExists: ['preventOverflow']
- };
+ // fire the first update to position the popper in the right place
+ this.update();
- function getSideOffsets(overflow, rect, preventedOffsets) {
- if (preventedOffsets === void 0) {
- preventedOffsets = {
- x: 0,
- y: 0
- };
+ var eventsEnabled = this.options.eventsEnabled;
+ if (eventsEnabled) {
+ // setup event listeners, they will take care of update the position in specific situations
+ this.enableEventListeners();
}
- return {
- top: overflow.top - rect.height - preventedOffsets.y,
- right: overflow.right - rect.width + preventedOffsets.x,
- bottom: overflow.bottom - rect.height + preventedOffsets.y,
- left: overflow.left - rect.width - preventedOffsets.x
- };
+ this.state.eventsEnabled = eventsEnabled;
}
- function isAnySideFullyClipped(overflow) {
- return [top, right, bottom, left].some(function (side) {
- return overflow[side] >= 0;
- });
- }
+ // We can't use class properties because they don't get listed in the
+ // class prototype and break stuff like Sinon stubs
- function hide(_ref) {
- var state = _ref.state,
- name = _ref.name;
- var referenceRect = state.rects.reference;
- var popperRect = state.rects.popper;
- var preventedOffsets = state.modifiersData.preventOverflow;
- var referenceOverflow = detectOverflow(state, {
- elementContext: 'reference'
- });
- var popperAltOverflow = detectOverflow(state, {
- altBoundary: true
- });
- var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
- var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
- var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
- var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
- state.modifiersData[name] = {
- referenceClippingOffsets: referenceClippingOffsets,
- popperEscapeOffsets: popperEscapeOffsets,
- isReferenceHidden: isReferenceHidden,
- hasPopperEscaped: hasPopperEscaped
- };
- state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), {}, {
- 'data-popper-reference-hidden': isReferenceHidden,
- 'data-popper-escaped': hasPopperEscaped
- });
- } // eslint-disable-next-line import/no-unused-modules
+ createClass(Popper, [{
+ key: 'update',
+ value: function update$$1() {
+ return update.call(this);
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy$$1() {
+ return destroy.call(this);
+ }
+ }, {
+ key: 'enableEventListeners',
+ value: function enableEventListeners$$1() {
+ return enableEventListeners.call(this);
+ }
+ }, {
+ key: 'disableEventListeners',
+ value: function disableEventListeners$$1() {
+ return disableEventListeners.call(this);
+ }
- var hide$1 = {
- name: 'hide',
- enabled: true,
- phase: 'main',
- requiresIfExists: ['preventOverflow'],
- fn: hide
- };
+ /**
+ * Schedules an update. It will run on the next UI update available.
+ * @method scheduleUpdate
+ * @memberof Popper
+ */
+
+
+ /**
+ * Collection of utilities useful when writing custom modifiers.
+ * Starting from version 1.7, this method is available only if you
+ * include `popper-utils.js` before `popper.js`.
+ *
+ * **DEPRECATION**: This way to access PopperUtils is deprecated
+ * and will be removed in v2! Use the PopperUtils module directly instead.
+ * Due to the high instability of the methods contained in Utils, we can't
+ * guarantee them to follow semver. Use them at your own risk!
+ * @static
+ * @private
+ * @type {Object}
+ * @deprecated since version 1.8
+ * @member Utils
+ * @memberof Popper
+ */
+
+ }]);
+ return Popper;
+}();
+
+/**
+ * The `referenceObject` is an object that provides an interface compatible with Popper.js
+ * and lets you use it as replacement of a real DOM node.
+ * You can use this method to position a popper relatively to a set of coordinates
+ * in case you don't have a DOM node to use as reference.
+ *
+ * ```
+ * new Popper(referenceObject, popperNode);
+ * ```
+ *
+ * NB: This feature isn't supported in Internet Explorer 10.
+ * @name referenceObject
+ * @property {Function} data.getBoundingClientRect
+ * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
+ * @property {number} data.clientWidth
+ * An ES6 getter that will return the width of the virtual reference element.
+ * @property {number} data.clientHeight
+ * An ES6 getter that will return the height of the virtual reference element.
+ */
- var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1];
- var createPopper = /*#__PURE__*/popperGenerator({
- defaultModifiers: defaultModifiers
- }); // eslint-disable-next-line import/no-unused-modules
- exports.createPopper = createPopper;
- exports.defaultModifiers = defaultModifiers;
- exports.detectOverflow = detectOverflow;
- exports.popperGenerator = popperGenerator;
+Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
+Popper.placements = placements;
+Popper.Defaults = Defaults;
- Object.defineProperty(exports, '__esModule', { value: true });
+return Popper;
})));
//# sourceMappingURL=popper.js.map