UNPKG

56.8 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var top = 'top';
6var bottom = 'bottom';
7var right = 'right';
8var left = 'left';
9var auto = 'auto';
10var basePlacements = [top, bottom, right, left];
11var start = 'start';
12var end = 'end';
13var clippingParents = 'clippingParents';
14var viewport = 'viewport';
15var popper = 'popper';
16var reference = 'reference';
17var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {
18 return acc.concat([placement + "-" + start, placement + "-" + end]);
19}, []);
20var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {
21 return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
22}, []); // modifiers that need to read the DOM
23
24var beforeRead = 'beforeRead';
25var read = 'read';
26var afterRead = 'afterRead'; // pure-logic modifiers
27
28var beforeMain = 'beforeMain';
29var main = 'main';
30var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
31
32var beforeWrite = 'beforeWrite';
33var write = 'write';
34var afterWrite = 'afterWrite';
35var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
36
37function getBasePlacement(placement) {
38 return placement.split('-')[0];
39}
40
41// Returns the layout rect of an element relative to its offsetParent. Layout
42// means it doesn't take into account transforms.
43function getLayoutRect(element) {
44 return {
45 x: element.offsetLeft,
46 y: element.offsetTop,
47 width: element.offsetWidth,
48 height: element.offsetHeight
49 };
50}
51
52function contains(parent, child) {
53 // $FlowFixMe: hasOwnProperty doesn't seem to work in tests
54 var isShadow = Boolean(child.getRootNode && child.getRootNode().host); // First, attempt with faster native method
55
56 if (parent.contains(child)) {
57 return true;
58 } // then fallback to custom implementation with Shadow DOM support
59 else if (isShadow) {
60 var next = child;
61
62 do {
63 if (next && parent.isSameNode(next)) {
64 return true;
65 } // $FlowFixMe: need a better way to handle this...
66
67
68 next = next.parentNode || next.host;
69 } while (next);
70 } // Give up, the result is false
71
72
73 return false;
74}
75
76/*:: import type { Window } from '../types'; */
77
78/*:: declare function getWindow(node: Node | Window): Window; */
79function getWindow(node) {
80 if (node.toString() !== '[object Window]') {
81 var ownerDocument = node.ownerDocument;
82 return ownerDocument ? ownerDocument.defaultView : window;
83 }
84
85 return node;
86}
87
88function getNodeName(element) {
89 return element ? (element.nodeName || '').toLowerCase() : null;
90}
91
92function getComputedStyle(element) {
93 return getWindow(element).getComputedStyle(element);
94}
95
96/*:: declare function isElement(node: mixed): boolean %checks(node instanceof
97 Element); */
98
99function isElement(node) {
100 var OwnElement = getWindow(node).Element;
101 return node instanceof OwnElement || node instanceof Element;
102}
103/*:: declare function isHTMLElement(node: mixed): boolean %checks(node instanceof
104 HTMLElement); */
105
106
107function isHTMLElement(node) {
108 var OwnElement = getWindow(node).HTMLElement;
109 return node instanceof OwnElement || node instanceof HTMLElement;
110}
111
112function isTableElement(element) {
113 return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
114}
115
116function getTrueOffsetParent(element) {
117 if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
118 getComputedStyle(element).position === 'fixed') {
119 return null;
120 }
121
122 return element.offsetParent;
123}
124
125function getOffsetParent(element) {
126 var window = getWindow(element);
127 var offsetParent = getTrueOffsetParent(element); // Find the nearest non-table offsetParent
128
129 while (offsetParent && isTableElement(offsetParent)) {
130 offsetParent = getTrueOffsetParent(offsetParent);
131 }
132
133 if (offsetParent && getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static') {
134 return window;
135 }
136
137 return offsetParent || window;
138}
139
140function getMainAxisFromPlacement(placement) {
141 return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
142}
143
144function within(min, value, max) {
145 return Math.max(min, Math.min(value, max));
146}
147
148function getFreshSideObject() {
149 return {
150 top: 0,
151 right: 0,
152 bottom: 0,
153 left: 0
154 };
155}
156
157function mergePaddingObject(paddingObject) {
158 return Object.assign({}, getFreshSideObject(), {}, paddingObject);
159}
160
161function expandToHashMap(value, keys) {
162 return keys.reduce(function (hashMap, key) {
163 hashMap[key] = value;
164 return hashMap;
165 }, {});
166}
167
168function arrow(_ref) {
169 var _state$modifiersData$;
170
171 var state = _ref.state,
172 name = _ref.name;
173 var arrowElement = state.elements.arrow;
174 var popperOffsets = state.modifiersData.popperOffsets;
175 var basePlacement = getBasePlacement(state.placement);
176 var axis = getMainAxisFromPlacement(basePlacement);
177 var isVertical = [left, right].indexOf(basePlacement) >= 0;
178 var len = isVertical ? 'height' : 'width';
179
180 if (!arrowElement || !popperOffsets) {
181 return;
182 }
183
184 var paddingObject = state.modifiersData[name + "#persistent"].padding;
185 var arrowRect = getLayoutRect(arrowElement);
186 var minProp = axis === 'y' ? top : left;
187 var maxProp = axis === 'y' ? bottom : right;
188 var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
189 var startDiff = popperOffsets[axis] - state.rects.reference[axis];
190 var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
191 var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
192 var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is
193 // outside of the popper bounds
194
195 var min = paddingObject[minProp];
196 var max = clientSize - arrowRect[len] - paddingObject[maxProp];
197 var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
198 var offset = within(min, center, max); // Prevents breaking syntax highlighting...
199
200 var axisProp = axis;
201 state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
202}
203
204function effect(_ref2) {
205 var state = _ref2.state,
206 options = _ref2.options,
207 name = _ref2.name;
208 var _options$element = options.element,
209 arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element,
210 _options$padding = options.padding,
211 padding = _options$padding === void 0 ? 0 : _options$padding;
212
213 if (arrowElement == null) {
214 return;
215 } // CSS selector
216
217
218 if (typeof arrowElement === 'string') {
219 arrowElement = state.elements.popper.querySelector(arrowElement);
220
221 if (!arrowElement) {
222 return;
223 }
224 }
225
226 if (!contains(state.elements.popper, arrowElement)) {
227 if (process.env.NODE_ENV !== "production") {
228 console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', 'element.'].join(' '));
229 }
230
231 return;
232 }
233
234 state.elements.arrow = arrowElement;
235 state.modifiersData[name + "#persistent"] = {
236 padding: mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements))
237 };
238} // eslint-disable-next-line import/no-unused-modules
239
240
241var arrow$1 = {
242 name: 'arrow',
243 enabled: true,
244 phase: 'main',
245 fn: arrow,
246 effect: effect,
247 requires: ['popperOffsets'],
248 requiresIfExists: ['preventOverflow']
249};
250
251function getDocumentElement(element) {
252 // $FlowFixMe: assume body is always available
253 return (isElement(element) ? element.ownerDocument : element.document).documentElement;
254}
255
256var unsetSides = {
257 top: 'auto',
258 right: 'auto',
259 bottom: 'auto',
260 left: 'auto'
261}; // Round the offsets to the nearest suitable subpixel based on the DPR.
262// Zooming can change the DPR, but it seems to report a value that will
263// cleanly divide the values into the appropriate subpixels.
264
265function roundOffsets(_ref) {
266 var x = _ref.x,
267 y = _ref.y;
268 var win = window;
269 var dpr = win.devicePixelRatio || 1;
270 return {
271 x: Math.round(x * dpr) / dpr || 0,
272 y: Math.round(y * dpr) / dpr || 0
273 };
274}
275
276function mapToStyles(_ref2) {
277 var _Object$assign2;
278
279 var popper = _ref2.popper,
280 popperRect = _ref2.popperRect,
281 placement = _ref2.placement,
282 offsets = _ref2.offsets,
283 position = _ref2.position,
284 gpuAcceleration = _ref2.gpuAcceleration,
285 adaptive = _ref2.adaptive;
286
287 var _roundOffsets = roundOffsets(offsets),
288 x = _roundOffsets.x,
289 y = _roundOffsets.y;
290
291 var hasX = offsets.hasOwnProperty('x');
292 var hasY = offsets.hasOwnProperty('y');
293 var sideX = left;
294 var sideY = top;
295 var win = window;
296
297 if (adaptive) {
298 var offsetParent = getOffsetParent(popper);
299
300 if (offsetParent === getWindow(popper)) {
301 offsetParent = getDocumentElement(popper);
302 } // $FlowFixMe: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it
303
304 /*:: offsetParent = (offsetParent: Element); */
305
306
307 if (placement === top) {
308 sideY = bottom;
309 y -= offsetParent.clientHeight - popperRect.height;
310 y *= gpuAcceleration ? 1 : -1;
311 }
312
313 if (placement === left) {
314 sideX = right;
315 x -= offsetParent.clientWidth - popperRect.width;
316 x *= gpuAcceleration ? 1 : -1;
317 }
318 }
319
320 var commonStyles = Object.assign({
321 position: position
322 }, adaptive && unsetSides);
323
324 if (gpuAcceleration) {
325 var _Object$assign;
326
327 return 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));
328 }
329
330 return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2));
331}
332
333function computeStyles(_ref3) {
334 var state = _ref3.state,
335 options = _ref3.options;
336 var _options$gpuAccelerat = options.gpuAcceleration,
337 gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,
338 _options$adaptive = options.adaptive,
339 adaptive = _options$adaptive === void 0 ? true : _options$adaptive;
340
341 if (process.env.NODE_ENV !== "production") {
342 var transitionProperty = getComputedStyle(state.elements.popper).transitionProperty || '';
343
344 if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) {
345 return transitionProperty.indexOf(property) >= 0;
346 })) {
347 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(' '));
348 }
349 }
350
351 var commonStyles = {
352 placement: getBasePlacement(state.placement),
353 popper: state.elements.popper,
354 popperRect: state.rects.popper,
355 gpuAcceleration: gpuAcceleration
356 };
357
358 if (state.modifiersData.popperOffsets != null) {
359 state.styles.popper = Object.assign({}, state.styles.popper, {}, mapToStyles(Object.assign({}, commonStyles, {
360 offsets: state.modifiersData.popperOffsets,
361 position: state.options.strategy,
362 adaptive: adaptive
363 })));
364 }
365
366 if (state.modifiersData.arrow != null) {
367 state.styles.arrow = Object.assign({}, state.styles.arrow, {}, mapToStyles(Object.assign({}, commonStyles, {
368 offsets: state.modifiersData.arrow,
369 position: 'absolute',
370 adaptive: false
371 })));
372 }
373
374 state.attributes.popper = Object.assign({}, state.attributes.popper, {
375 'data-popper-placement': state.placement
376 });
377} // eslint-disable-next-line import/no-unused-modules
378
379
380var computeStyles$1 = {
381 name: 'computeStyles',
382 enabled: true,
383 phase: 'beforeWrite',
384 fn: computeStyles,
385 data: {}
386};
387
388var passive = {
389 passive: true
390};
391
392function effect$1(_ref) {
393 var state = _ref.state,
394 instance = _ref.instance,
395 options = _ref.options;
396 var _options$scroll = options.scroll,
397 scroll = _options$scroll === void 0 ? true : _options$scroll,
398 _options$resize = options.resize,
399 resize = _options$resize === void 0 ? true : _options$resize;
400 var window = getWindow(state.elements.popper);
401 var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);
402
403 if (scroll) {
404 scrollParents.forEach(function (scrollParent) {
405 scrollParent.addEventListener('scroll', instance.update, passive);
406 });
407 }
408
409 if (resize) {
410 window.addEventListener('resize', instance.update, passive);
411 }
412
413 return function () {
414 if (scroll) {
415 scrollParents.forEach(function (scrollParent) {
416 scrollParent.removeEventListener('scroll', instance.update, passive);
417 });
418 }
419
420 if (resize) {
421 window.removeEventListener('resize', instance.update, passive);
422 }
423 };
424} // eslint-disable-next-line import/no-unused-modules
425
426
427var eventListeners = {
428 name: 'eventListeners',
429 enabled: true,
430 phase: 'write',
431 fn: function fn() {},
432 effect: effect$1,
433 data: {}
434};
435
436var hash = {
437 left: 'right',
438 right: 'left',
439 bottom: 'top',
440 top: 'bottom'
441};
442function getOppositePlacement(placement) {
443 return placement.replace(/left|right|bottom|top/g, function (matched) {
444 return hash[matched];
445 });
446}
447
448var hash$1 = {
449 start: 'end',
450 end: 'start'
451};
452function getOppositeVariationPlacement(placement) {
453 return placement.replace(/start|end/g, function (matched) {
454 return hash$1[matched];
455 });
456}
457
458function getBoundingClientRect(element) {
459 var rect = element.getBoundingClientRect();
460 return {
461 width: rect.width,
462 height: rect.height,
463 top: rect.top,
464 right: rect.right,
465 bottom: rect.bottom,
466 left: rect.left,
467 x: rect.left,
468 y: rect.top
469 };
470}
471
472function getViewportRect(element) {
473 var win = getWindow(element);
474 var visualViewport = win.visualViewport;
475 var width = win.innerWidth;
476 var height = win.innerHeight; // We don't know which browsers have buggy or odd implementations of this, so
477 // for now we're only applying it to iOS to fix the keyboard issue.
478 // Investigation required
479
480 if (visualViewport && /iPhone|iPod|iPad/.test(navigator.platform)) {
481 width = visualViewport.width;
482 height = visualViewport.height;
483 }
484
485 return {
486 width: width,
487 height: height,
488 x: 0,
489 y: 0
490 };
491}
492
493function getWindowScroll(node) {
494 var win = getWindow(node);
495 var scrollLeft = win.pageXOffset;
496 var scrollTop = win.pageYOffset;
497 return {
498 scrollLeft: scrollLeft,
499 scrollTop: scrollTop
500 };
501}
502
503function getHTMLElementScroll(element) {
504 return {
505 scrollLeft: element.scrollLeft,
506 scrollTop: element.scrollTop
507 };
508}
509
510function getNodeScroll(node) {
511 if (node === getWindow(node) || !isHTMLElement(node)) {
512 return getWindowScroll(node);
513 } else {
514 return getHTMLElementScroll(node);
515 }
516}
517
518function getWindowScrollBarX(element) {
519 // If <html> has a CSS width greater than the viewport, then this will be
520 // incorrect for RTL.
521 // Popper 1 is broken in this case and never had a bug report so let's assume
522 // it's not an issue. I don't think anyone ever specifies width on <html>
523 // anyway.
524 // Browsers where the left scrollbar doesn't cause an issue report `0` for
525 // this (e.g. Edge 2019, IE11, Safari)
526 return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
527}
528
529// Composite means it takes into account transforms as well as layout.
530
531function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
532 if (isFixed === void 0) {
533 isFixed = false;
534 }
535
536 var documentElement;
537 var rect = getBoundingClientRect(elementOrVirtualElement);
538 var scroll = {
539 scrollLeft: 0,
540 scrollTop: 0
541 };
542 var offsets = {
543 x: 0,
544 y: 0
545 };
546
547 if (!isFixed) {
548 if (getNodeName(offsetParent) !== 'body') {
549 scroll = getNodeScroll(offsetParent);
550 }
551
552 if (isHTMLElement(offsetParent)) {
553 offsets = getBoundingClientRect(offsetParent);
554 offsets.x += offsetParent.clientLeft;
555 offsets.y += offsetParent.clientTop;
556 } else if (documentElement = getDocumentElement(offsetParent)) {
557 offsets.x = getWindowScrollBarX(documentElement);
558 }
559 }
560
561 return {
562 x: rect.left + scroll.scrollLeft - offsets.x,
563 y: rect.top + scroll.scrollTop - offsets.y,
564 width: rect.width,
565 height: rect.height
566 };
567}
568
569function getDocumentRect(element) {
570 var win = getWindow(element);
571 var winScroll = getWindowScroll(element);
572 var documentRect = getCompositeRect(getDocumentElement(element), win);
573 documentRect.height = Math.max(documentRect.height, win.innerHeight);
574 documentRect.width = Math.max(documentRect.width, win.innerWidth);
575 documentRect.x = -winScroll.scrollLeft;
576 documentRect.y = -winScroll.scrollTop;
577 return documentRect;
578}
579
580function getParentNode(element) {
581 if (getNodeName(element) === 'html') {
582 return element;
583 }
584
585 return (// $FlowFixMe: this is a quicker (but less type safe) way to save quite some bytes from the bundle
586 element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
587 element.parentNode || // DOM Element detected
588 // $FlowFixMe: need a better way to handle this...
589 element.host || // ShadowRoot detected
590 // $FlowFixMe: HTMLElement is a Node
591 getDocumentElement(element) // fallback
592
593 );
594}
595
596function getScrollParent(node) {
597 if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
598 // $FlowFixMe: assume body is always available
599 return node.ownerDocument.body;
600 }
601
602 if (isHTMLElement(node)) {
603 // Firefox wants us to check `-x` and `-y` variations as well
604 var _getComputedStyle = getComputedStyle(node),
605 overflow = _getComputedStyle.overflow,
606 overflowX = _getComputedStyle.overflowX,
607 overflowY = _getComputedStyle.overflowY;
608
609 if (/auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX)) {
610 return node;
611 }
612 }
613
614 return getScrollParent(getParentNode(node));
615}
616
617function listScrollParents(element, list) {
618 if (list === void 0) {
619 list = [];
620 }
621
622 var scrollParent = getScrollParent(element);
623 var isBody = getNodeName(scrollParent) === 'body';
624 var win = getWindow(scrollParent);
625 var target = isBody ? [win].concat(win.visualViewport || []) : scrollParent;
626 var updatedList = list.concat(target);
627 return isBody ? updatedList : // $FlowFixMe: isBody tells us target will be an HTMLElement here
628 updatedList.concat(listScrollParents(getParentNode(target)));
629}
630
631function toNumber(cssValue) {
632 return parseFloat(cssValue) || 0;
633}
634
635function getBorders(element) {
636 var computedStyle = isHTMLElement(element) ? getComputedStyle(element) : {};
637 return {
638 top: toNumber(computedStyle.borderTopWidth),
639 right: toNumber(computedStyle.borderRightWidth),
640 bottom: toNumber(computedStyle.borderBottomWidth),
641 left: toNumber(computedStyle.borderLeftWidth)
642 };
643}
644
645function getDecorations(element) {
646 var win = getWindow(element);
647 var borders = getBorders(element);
648 var isHTML = getNodeName(element) === 'html';
649 var winScrollBarX = getWindowScrollBarX(element);
650 var x = element.clientWidth + borders.right;
651 var y = element.clientHeight + borders.bottom; // HACK:
652 // document.documentElement.clientHeight on iOS reports the height of the
653 // viewport including the bottom bar, even if the bottom bar isn't visible.
654 // If the difference between window innerHeight and html clientHeight is more
655 // than 50, we assume it's a mobile bottom bar and ignore scrollbars.
656 // * A 50px thick scrollbar is likely non-existent (macOS is 15px and Windows
657 // is about 17px)
658 // * The mobile bar is 114px tall
659
660 if (isHTML && win.innerHeight - element.clientHeight > 50) {
661 y = win.innerHeight - borders.bottom;
662 }
663
664 return {
665 top: isHTML ? 0 : element.clientTop,
666 right: // RTL scrollbar (scrolling containers only)
667 element.clientLeft > borders.left ? borders.right : // LTR scrollbar
668 isHTML ? win.innerWidth - x - winScrollBarX : element.offsetWidth - x,
669 bottom: isHTML ? win.innerHeight - y : element.offsetHeight - y,
670 left: isHTML ? winScrollBarX : element.clientLeft
671 };
672}
673
674function rectToClientRect(rect) {
675 return Object.assign({}, rect, {
676 left: rect.x,
677 top: rect.y,
678 right: rect.x + rect.width,
679 bottom: rect.y + rect.height
680 });
681}
682
683function getClientRectFromMixedType(element, clippingParent) {
684 return clippingParent === viewport ? rectToClientRect(getViewportRect(element)) : isHTMLElement(clippingParent) ? getBoundingClientRect(clippingParent) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
685} // A "clipping parent" is an overflowable container with the characteristic of
686// clipping (or hiding) overflowing elements with a position different from
687// `initial`
688
689
690function getClippingParents(element) {
691 var clippingParents = listScrollParents(element);
692 var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;
693 var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
694
695 if (!isElement(clipperElement)) {
696 return [];
697 } // $FlowFixMe: https://github.com/facebook/flow/issues/1414
698
699
700 return clippingParents.filter(function (clippingParent) {
701 return isElement(clippingParent) && contains(clippingParent, clipperElement);
702 });
703} // Gets the maximum area that the element is visible in due to any number of
704// clipping parents
705
706
707function getClippingRect(element, boundary, rootBoundary) {
708 var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
709 var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
710 var firstClippingParent = clippingParents[0];
711 var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
712 var rect = getClientRectFromMixedType(element, clippingParent);
713 var decorations = getDecorations(isHTMLElement(clippingParent) ? clippingParent : getDocumentElement(element));
714 accRect.top = Math.max(rect.top + decorations.top, accRect.top);
715 accRect.right = Math.min(rect.right - decorations.right, accRect.right);
716 accRect.bottom = Math.min(rect.bottom - decorations.bottom, accRect.bottom);
717 accRect.left = Math.max(rect.left + decorations.left, accRect.left);
718 return accRect;
719 }, getClientRectFromMixedType(element, firstClippingParent));
720 clippingRect.width = clippingRect.right - clippingRect.left;
721 clippingRect.height = clippingRect.bottom - clippingRect.top;
722 clippingRect.x = clippingRect.left;
723 clippingRect.y = clippingRect.top;
724 return clippingRect;
725}
726
727function getVariation(placement) {
728 return placement.split('-')[1];
729}
730
731function computeOffsets(_ref) {
732 var reference = _ref.reference,
733 element = _ref.element,
734 placement = _ref.placement;
735 var basePlacement = placement ? getBasePlacement(placement) : null;
736 var variation = placement ? getVariation(placement) : null;
737 var commonX = reference.x + reference.width / 2 - element.width / 2;
738 var commonY = reference.y + reference.height / 2 - element.height / 2;
739 var offsets;
740
741 switch (basePlacement) {
742 case top:
743 offsets = {
744 x: commonX,
745 y: reference.y - element.height
746 };
747 break;
748
749 case bottom:
750 offsets = {
751 x: commonX,
752 y: reference.y + reference.height
753 };
754 break;
755
756 case right:
757 offsets = {
758 x: reference.x + reference.width,
759 y: commonY
760 };
761 break;
762
763 case left:
764 offsets = {
765 x: reference.x - element.width,
766 y: commonY
767 };
768 break;
769
770 default:
771 offsets = {
772 x: reference.x,
773 y: reference.y
774 };
775 }
776
777 var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
778
779 if (mainAxis != null) {
780 var len = mainAxis === 'y' ? 'height' : 'width';
781
782 switch (variation) {
783 case start:
784 offsets[mainAxis] = Math.floor(offsets[mainAxis]) - Math.floor(reference[len] / 2 - element[len] / 2);
785 break;
786
787 case end:
788 offsets[mainAxis] = Math.floor(offsets[mainAxis]) + Math.ceil(reference[len] / 2 - element[len] / 2);
789 break;
790 }
791 }
792
793 return offsets;
794}
795
796function detectOverflow(state, options) {
797 if (options === void 0) {
798 options = {};
799 }
800
801 var _options = options,
802 _options$placement = _options.placement,
803 placement = _options$placement === void 0 ? state.placement : _options$placement,
804 _options$boundary = _options.boundary,
805 boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,
806 _options$rootBoundary = _options.rootBoundary,
807 rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,
808 _options$elementConte = _options.elementContext,
809 elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,
810 _options$altBoundary = _options.altBoundary,
811 altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,
812 _options$padding = _options.padding,
813 padding = _options$padding === void 0 ? 0 : _options$padding;
814 var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
815 var altContext = elementContext === popper ? reference : popper;
816 var referenceElement = state.elements.reference;
817 var popperRect = state.rects.popper;
818 var element = state.elements[altBoundary ? altContext : elementContext];
819 var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary);
820 var referenceClientRect = getBoundingClientRect(referenceElement);
821 var popperOffsets = computeOffsets({
822 reference: referenceClientRect,
823 element: popperRect,
824 strategy: 'absolute',
825 placement: placement
826 });
827 var popperClientRect = rectToClientRect(Object.assign({}, popperRect, {}, popperOffsets));
828 var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect
829 // 0 or negative = within the clipping rect
830
831 var overflowOffsets = {
832 top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
833 bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
834 left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
835 right: elementClientRect.right - clippingClientRect.right + paddingObject.right
836 };
837 var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element
838
839 if (elementContext === popper && offsetData) {
840 var offset = offsetData[placement];
841 Object.keys(overflowOffsets).forEach(function (key) {
842 var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
843 var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
844 overflowOffsets[key] += offset[axis] * multiply;
845 });
846 }
847
848 return overflowOffsets;
849}
850
851/*:: type OverflowsMap = { [ComputedPlacement]: number }; */
852
853/*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */
854function computeAutoPlacement(state, options) {
855 if (options === void 0) {
856 options = {};
857 }
858
859 var _options = options,
860 placement = _options.placement,
861 boundary = _options.boundary,
862 rootBoundary = _options.rootBoundary,
863 padding = _options.padding,
864 flipVariations = _options.flipVariations,
865 _options$allowedAutoP = _options.allowedAutoPlacements,
866 allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
867 var variation = getVariation(placement);
868 var placements$1 = (variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {
869 return getVariation(placement) === variation;
870 }) : basePlacements).filter(function (placement) {
871 return allowedAutoPlacements.indexOf(placement) >= 0;
872 }); // $FlowFixMe: Flow seems to have problems with two array unions...
873
874 var overflows = placements$1.reduce(function (acc, placement) {
875 acc[placement] = detectOverflow(state, {
876 placement: placement,
877 boundary: boundary,
878 rootBoundary: rootBoundary,
879 padding: padding
880 })[getBasePlacement(placement)];
881 return acc;
882 }, {});
883 return Object.keys(overflows).sort(function (a, b) {
884 return overflows[a] - overflows[b];
885 });
886}
887
888function getExpandedFallbackPlacements(placement) {
889 if (getBasePlacement(placement) === auto) {
890 return [];
891 }
892
893 var oppositePlacement = getOppositePlacement(placement);
894 return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
895}
896
897function flip(_ref) {
898 var state = _ref.state,
899 options = _ref.options,
900 name = _ref.name;
901
902 if (state.modifiersData[name]._skip) {
903 return;
904 }
905
906 var specifiedFallbackPlacements = options.fallbackPlacements,
907 padding = options.padding,
908 boundary = options.boundary,
909 rootBoundary = options.rootBoundary,
910 altBoundary = options.altBoundary,
911 _options$flipVariatio = options.flipVariations,
912 flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,
913 allowedAutoPlacements = options.allowedAutoPlacements;
914 var preferredPlacement = state.options.placement;
915 var basePlacement = getBasePlacement(preferredPlacement);
916 var isBasePlacement = basePlacement === preferredPlacement;
917 var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
918 var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {
919 return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {
920 placement: placement,
921 boundary: boundary,
922 rootBoundary: rootBoundary,
923 padding: padding,
924 flipVariations: flipVariations,
925 allowedAutoPlacements: allowedAutoPlacements
926 }) : placement);
927 }, []);
928 var referenceRect = state.rects.reference;
929 var popperRect = state.rects.popper;
930 var checksMap = new Map();
931 var makeFallbackChecks = true;
932 var firstFittingPlacement = placements[0];
933
934 for (var i = 0; i < placements.length; i++) {
935 var placement = placements[i];
936
937 var _basePlacement = getBasePlacement(placement);
938
939 var isStartVariation = getVariation(placement) === start;
940 var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
941 var len = isVertical ? 'width' : 'height';
942 var overflow = detectOverflow(state, {
943 placement: placement,
944 boundary: boundary,
945 rootBoundary: rootBoundary,
946 altBoundary: altBoundary,
947 padding: padding
948 });
949 var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
950
951 if (referenceRect[len] > popperRect[len]) {
952 mainVariationSide = getOppositePlacement(mainVariationSide);
953 }
954
955 var altVariationSide = getOppositePlacement(mainVariationSide);
956 var checks = [overflow[_basePlacement] <= 0, overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0];
957
958 if (checks.every(function (check) {
959 return check;
960 })) {
961 firstFittingPlacement = placement;
962 makeFallbackChecks = false;
963 break;
964 }
965
966 checksMap.set(placement, checks);
967 }
968
969 if (makeFallbackChecks) {
970 // `2` may be desired in some cases – research later
971 var numberOfChecks = flipVariations ? 3 : 1;
972
973 var _loop = function _loop(_i) {
974 var fittingPlacement = placements.find(function (placement) {
975 var checks = checksMap.get(placement);
976
977 if (checks) {
978 return checks.slice(0, _i).every(function (check) {
979 return check;
980 });
981 }
982 });
983
984 if (fittingPlacement) {
985 firstFittingPlacement = fittingPlacement;
986 return "break";
987 }
988 };
989
990 for (var _i = numberOfChecks; _i > 0; _i--) {
991 var _ret = _loop(_i);
992
993 if (_ret === "break") break;
994 }
995 }
996
997 if (state.placement !== firstFittingPlacement) {
998 state.modifiersData[name]._skip = true;
999 state.placement = firstFittingPlacement;
1000 state.reset = true;
1001 }
1002} // eslint-disable-next-line import/no-unused-modules
1003
1004
1005var flip$1 = {
1006 name: 'flip',
1007 enabled: true,
1008 phase: 'main',
1009 fn: flip,
1010 requiresIfExists: ['offset'],
1011 data: {
1012 _skip: false
1013 }
1014};
1015
1016function getSideOffsets(overflow, rect, preventedOffsets) {
1017 if (preventedOffsets === void 0) {
1018 preventedOffsets = {
1019 x: 0,
1020 y: 0
1021 };
1022 }
1023
1024 return {
1025 top: overflow.top - rect.height - preventedOffsets.y,
1026 right: overflow.right - rect.width + preventedOffsets.x,
1027 bottom: overflow.bottom - rect.height + preventedOffsets.y,
1028 left: overflow.left - rect.width - preventedOffsets.x
1029 };
1030}
1031
1032function isAnySideFullyClipped(overflow) {
1033 return [top, right, bottom, left].some(function (side) {
1034 return overflow[side] >= 0;
1035 });
1036}
1037
1038function hide(_ref) {
1039 var state = _ref.state,
1040 name = _ref.name;
1041 var referenceRect = state.rects.reference;
1042 var popperRect = state.rects.popper;
1043 var preventedOffsets = state.modifiersData.preventOverflow;
1044 var referenceOverflow = detectOverflow(state, {
1045 elementContext: 'reference'
1046 });
1047 var popperAltOverflow = detectOverflow(state, {
1048 altBoundary: true
1049 });
1050 var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
1051 var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
1052 var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
1053 var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
1054 state.modifiersData[name] = {
1055 referenceClippingOffsets: referenceClippingOffsets,
1056 popperEscapeOffsets: popperEscapeOffsets,
1057 isReferenceHidden: isReferenceHidden,
1058 hasPopperEscaped: hasPopperEscaped
1059 };
1060 state.attributes.popper = Object.assign({}, state.attributes.popper, {
1061 'data-popper-reference-hidden': isReferenceHidden,
1062 'data-popper-escaped': hasPopperEscaped
1063 });
1064} // eslint-disable-next-line import/no-unused-modules
1065
1066
1067var hide$1 = {
1068 name: 'hide',
1069 enabled: true,
1070 phase: 'main',
1071 requiresIfExists: ['preventOverflow'],
1072 fn: hide
1073};
1074
1075function distanceAndSkiddingToXY(placement, rects, offset) {
1076 var basePlacement = getBasePlacement(placement);
1077 var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;
1078
1079 var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, {
1080 placement: placement
1081 })) : offset,
1082 skidding = _ref[0],
1083 distance = _ref[1];
1084
1085 skidding = skidding || 0;
1086 distance = (distance || 0) * invertDistance;
1087 return [left, right].indexOf(basePlacement) >= 0 ? {
1088 x: distance,
1089 y: skidding
1090 } : {
1091 x: skidding,
1092 y: distance
1093 };
1094}
1095
1096function offset(_ref2) {
1097 var state = _ref2.state,
1098 options = _ref2.options,
1099 name = _ref2.name;
1100 var _options$offset = options.offset,
1101 offset = _options$offset === void 0 ? [0, 0] : _options$offset;
1102 var data = placements.reduce(function (acc, placement) {
1103 acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);
1104 return acc;
1105 }, {});
1106 var _data$state$placement = data[state.placement],
1107 x = _data$state$placement.x,
1108 y = _data$state$placement.y;
1109
1110 if (state.modifiersData.popperOffsets != null) {
1111 state.modifiersData.popperOffsets.x += x;
1112 state.modifiersData.popperOffsets.y += y;
1113 }
1114
1115 state.modifiersData[name] = data;
1116} // eslint-disable-next-line import/no-unused-modules
1117
1118
1119var offset$1 = {
1120 name: 'offset',
1121 enabled: true,
1122 phase: 'main',
1123 requires: ['popperOffsets'],
1124 fn: offset
1125};
1126
1127function popperOffsets(_ref) {
1128 var state = _ref.state,
1129 name = _ref.name;
1130 // Offsets are the actual position the popper needs to have to be
1131 // properly positioned near its reference element
1132 // This is the most basic placement, and will be adjusted by
1133 // the modifiers in the next step
1134 state.modifiersData[name] = computeOffsets({
1135 reference: state.rects.reference,
1136 element: state.rects.popper,
1137 strategy: 'absolute',
1138 placement: state.placement
1139 });
1140} // eslint-disable-next-line import/no-unused-modules
1141
1142
1143var popperOffsets$1 = {
1144 name: 'popperOffsets',
1145 enabled: true,
1146 phase: 'read',
1147 fn: popperOffsets,
1148 data: {}
1149};
1150
1151function getAltAxis(axis) {
1152 return axis === 'x' ? 'y' : 'x';
1153}
1154
1155function preventOverflow(_ref) {
1156 var state = _ref.state,
1157 options = _ref.options,
1158 name = _ref.name;
1159 var _options$mainAxis = options.mainAxis,
1160 checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
1161 _options$altAxis = options.altAxis,
1162 checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,
1163 boundary = options.boundary,
1164 rootBoundary = options.rootBoundary,
1165 altBoundary = options.altBoundary,
1166 padding = options.padding,
1167 _options$tether = options.tether,
1168 tether = _options$tether === void 0 ? true : _options$tether,
1169 _options$tetherOffset = options.tetherOffset,
1170 tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
1171 var overflow = detectOverflow(state, {
1172 boundary: boundary,
1173 rootBoundary: rootBoundary,
1174 padding: padding,
1175 altBoundary: altBoundary
1176 });
1177 var basePlacement = getBasePlacement(state.placement);
1178 var variation = getVariation(state.placement);
1179 var isBasePlacement = !variation;
1180 var mainAxis = getMainAxisFromPlacement(basePlacement);
1181 var altAxis = getAltAxis(mainAxis);
1182 var popperOffsets = state.modifiersData.popperOffsets;
1183 var referenceRect = state.rects.reference;
1184 var popperRect = state.rects.popper;
1185 var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {
1186 placement: state.placement
1187 })) : tetherOffset;
1188 var data = {
1189 x: 0,
1190 y: 0
1191 };
1192
1193 if (!popperOffsets) {
1194 return;
1195 }
1196
1197 if (checkMainAxis) {
1198 var mainSide = mainAxis === 'y' ? top : left;
1199 var altSide = mainAxis === 'y' ? bottom : right;
1200 var len = mainAxis === 'y' ? 'height' : 'width';
1201 var offset = popperOffsets[mainAxis];
1202 var min = popperOffsets[mainAxis] + overflow[mainSide];
1203 var max = popperOffsets[mainAxis] - overflow[altSide];
1204 var additive = tether ? -popperRect[len] / 2 : 0;
1205 var minLen = variation === start ? referenceRect[len] : popperRect[len];
1206 var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go
1207 // outside the reference bounds
1208
1209 var arrowElement = state.elements.arrow;
1210 var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
1211 width: 0,
1212 height: 0
1213 };
1214 var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();
1215 var arrowPaddingMin = arrowPaddingObject[mainSide];
1216 var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want
1217 // to include its full size in the calculation. If the reference is small
1218 // and near the edge of a boundary, the popper can overflow even if the
1219 // reference is not overflowing as well (e.g. virtual elements with no
1220 // width or height)
1221
1222 var arrowLen = within(0, referenceRect[len], arrowRect[len]);
1223 var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - tetherOffsetValue : minLen - arrowLen - arrowPaddingMin - tetherOffsetValue;
1224 var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + tetherOffsetValue : maxLen + arrowLen + arrowPaddingMax + tetherOffsetValue;
1225 var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
1226 var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
1227 var offsetModifierValue = state.modifiersData.offset ? state.modifiersData.offset[state.placement][mainAxis] : 0;
1228 var tetherMin = popperOffsets[mainAxis] + minOffset - offsetModifierValue - clientOffset;
1229 var tetherMax = popperOffsets[mainAxis] + maxOffset - offsetModifierValue;
1230 var preventedOffset = within(tether ? Math.min(min, tetherMin) : min, offset, tether ? Math.max(max, tetherMax) : max);
1231 popperOffsets[mainAxis] = preventedOffset;
1232 data[mainAxis] = preventedOffset - offset;
1233 }
1234
1235 if (checkAltAxis) {
1236 var _mainSide = mainAxis === 'x' ? top : left;
1237
1238 var _altSide = mainAxis === 'x' ? bottom : right;
1239
1240 var _offset = popperOffsets[altAxis];
1241
1242 var _min = _offset + overflow[_mainSide];
1243
1244 var _max = _offset - overflow[_altSide];
1245
1246 var _preventedOffset = within(_min, _offset, _max);
1247
1248 popperOffsets[altAxis] = _preventedOffset;
1249 data[altAxis] = _preventedOffset - _offset;
1250 }
1251
1252 state.modifiersData[name] = data;
1253} // eslint-disable-next-line import/no-unused-modules
1254
1255
1256var preventOverflow$1 = {
1257 name: 'preventOverflow',
1258 enabled: true,
1259 phase: 'main',
1260 fn: preventOverflow,
1261 requiresIfExists: ['offset']
1262};
1263
1264function order(modifiers) {
1265 var map = new Map();
1266 var visited = new Set();
1267 var result = [];
1268 modifiers.forEach(function (modifier) {
1269 map.set(modifier.name, modifier);
1270 }); // On visiting object, check for its dependencies and visit them recursively
1271
1272 function sort(modifier) {
1273 visited.add(modifier.name);
1274 var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
1275 requires.forEach(function (dep) {
1276 if (!visited.has(dep)) {
1277 var depModifier = map.get(dep);
1278
1279 if (depModifier) {
1280 sort(depModifier);
1281 }
1282 }
1283 });
1284 result.push(modifier);
1285 }
1286
1287 modifiers.forEach(function (modifier) {
1288 if (!visited.has(modifier.name)) {
1289 // check for visited object
1290 sort(modifier);
1291 }
1292 });
1293 return result;
1294}
1295
1296function orderModifiers(modifiers) {
1297 // order based on dependencies
1298 var orderedModifiers = order(modifiers); // order based on phase
1299
1300 return modifierPhases.reduce(function (acc, phase) {
1301 return acc.concat(orderedModifiers.filter(function (modifier) {
1302 return modifier.phase === phase;
1303 }));
1304 }, []);
1305}
1306
1307function debounce(fn) {
1308 var pending;
1309 return function () {
1310 if (!pending) {
1311 pending = new Promise(function (resolve) {
1312 Promise.resolve().then(function () {
1313 pending = undefined;
1314 resolve(fn());
1315 });
1316 });
1317 }
1318
1319 return pending;
1320 };
1321}
1322
1323function format(str) {
1324 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1325 args[_key - 1] = arguments[_key];
1326 }
1327
1328 return [].concat(args).reduce(function (p, c) {
1329 return p.replace(/%s/, c);
1330 }, str);
1331}
1332
1333var INVALID_MODIFIER_ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s';
1334var MISSING_DEPENDENCY_ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available';
1335var VALID_PROPERTIES = ['name', 'enabled', 'phase', 'fn', 'effect', 'requires', 'options'];
1336function validateModifiers(modifiers) {
1337 modifiers.forEach(function (modifier) {
1338 Object.keys(modifier).forEach(function (key) {
1339 switch (key) {
1340 case 'name':
1341 if (typeof modifier.name !== 'string') {
1342 console.error(format(INVALID_MODIFIER_ERROR, String(modifier.name), '"name"', '"string"', "\"" + String(modifier.name) + "\""));
1343 }
1344
1345 break;
1346
1347 case 'enabled':
1348 if (typeof modifier.enabled !== 'boolean') {
1349 console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"enabled"', '"boolean"', "\"" + String(modifier.enabled) + "\""));
1350 }
1351
1352 case 'phase':
1353 if (modifierPhases.indexOf(modifier.phase) < 0) {
1354 console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"phase"', "either " + modifierPhases.join(', '), "\"" + String(modifier.phase) + "\""));
1355 }
1356
1357 break;
1358
1359 case 'fn':
1360 if (typeof modifier.fn !== 'function') {
1361 console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"fn"', '"function"', "\"" + String(modifier.fn) + "\""));
1362 }
1363
1364 break;
1365
1366 case 'effect':
1367 if (typeof modifier.effect !== 'function') {
1368 console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"effect"', '"function"', "\"" + String(modifier.fn) + "\""));
1369 }
1370
1371 break;
1372
1373 case 'requires':
1374 if (!Array.isArray(modifier.requires)) {
1375 console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requires"', '"array"', "\"" + String(modifier.requires) + "\""));
1376 }
1377
1378 break;
1379
1380 case 'requiresIfExists':
1381 if (!Array.isArray(modifier.requiresIfExists)) {
1382 console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requiresIfExists"', '"array"', "\"" + String(modifier.requiresIfExists) + "\""));
1383 }
1384
1385 break;
1386
1387 case 'options':
1388 case 'data':
1389 break;
1390
1391 default:
1392 console.error("PopperJS: an invalid property has been provided to the \"" + modifier.name + "\" modifier, valid properties are " + VALID_PROPERTIES.map(function (s) {
1393 return "\"" + s + "\"";
1394 }).join(', ') + "; but \"" + key + "\" was provided.");
1395 }
1396
1397 modifier.requires && modifier.requires.forEach(function (requirement) {
1398 if (modifiers.find(function (mod) {
1399 return mod.name === requirement;
1400 }) == null) {
1401 console.error(format(MISSING_DEPENDENCY_ERROR, String(modifier.name), requirement, requirement));
1402 }
1403 });
1404 });
1405 });
1406}
1407
1408function uniqueBy(arr, fn) {
1409 var identifiers = new Set();
1410 return arr.filter(function (item) {
1411 var identifier = fn(item);
1412
1413 if (!identifiers.has(identifier)) {
1414 identifiers.add(identifier);
1415 return true;
1416 }
1417 });
1418}
1419
1420function mergeByName(modifiers) {
1421 var merged = modifiers.reduce(function (merged, current) {
1422 var existing = merged[current.name];
1423 merged[current.name] = existing ? Object.assign({}, existing, {}, current, {
1424 options: Object.assign({}, existing.options, {}, current.options),
1425 data: Object.assign({}, existing.data, {}, current.data)
1426 }) : current;
1427 return merged;
1428 }, {}); // IE11 does not support Object.values
1429
1430 return Object.keys(merged).map(function (key) {
1431 return merged[key];
1432 });
1433}
1434
1435var INVALID_ELEMENT_ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.';
1436var INFINITE_LOOP_ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.';
1437var DEFAULT_OPTIONS = {
1438 placement: 'bottom',
1439 modifiers: [],
1440 strategy: 'absolute'
1441};
1442
1443function areValidElements() {
1444 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1445 args[_key] = arguments[_key];
1446 }
1447
1448 return !args.some(function (element) {
1449 return !(element && typeof element.getBoundingClientRect === 'function');
1450 });
1451}
1452
1453function popperGenerator(generatorOptions) {
1454 if (generatorOptions === void 0) {
1455 generatorOptions = {};
1456 }
1457
1458 var _generatorOptions = generatorOptions,
1459 _generatorOptions$def = _generatorOptions.defaultModifiers,
1460 defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
1461 _generatorOptions$def2 = _generatorOptions.defaultOptions,
1462 defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
1463 return function createPopper(reference, popper, options) {
1464 if (options === void 0) {
1465 options = defaultOptions;
1466 }
1467
1468 var state = {
1469 placement: 'bottom',
1470 orderedModifiers: [],
1471 options: Object.assign({}, DEFAULT_OPTIONS, {}, defaultOptions),
1472 modifiersData: {},
1473 elements: {
1474 reference: reference,
1475 popper: popper
1476 },
1477 attributes: {},
1478 styles: {}
1479 };
1480 var effectCleanupFns = [];
1481 var isDestroyed = false;
1482 var instance = {
1483 state: state,
1484 setOptions: function setOptions(options) {
1485 cleanupModifierEffects();
1486 state.options = Object.assign({}, defaultOptions, {}, state.options, {}, options);
1487 state.scrollParents = {
1488 reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
1489 popper: listScrollParents(popper)
1490 }; // Orders the modifiers based on their dependencies and `phase`
1491 // properties
1492
1493 var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
1494
1495 state.orderedModifiers = orderedModifiers.filter(function (m) {
1496 return m.enabled;
1497 }); // Validate the provided modifiers so that the consumer will get warned
1498 // if one of the modifiers is invalid for any reason
1499
1500 if (process.env.NODE_ENV !== "production") {
1501 var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function (_ref) {
1502 var name = _ref.name;
1503 return name;
1504 });
1505 validateModifiers(modifiers);
1506
1507 if (getBasePlacement(state.options.placement) === auto) {
1508 var flipModifier = state.orderedModifiers.find(function (_ref2) {
1509 var name = _ref2.name;
1510 return name === 'flip';
1511 });
1512
1513 if (!flipModifier) {
1514 console.error(['Popper: "auto" placements require the "flip" modifier be', 'present and enabled to work.'].join(' '));
1515 }
1516 }
1517
1518 var _getComputedStyle = getComputedStyle(popper),
1519 marginTop = _getComputedStyle.marginTop,
1520 marginRight = _getComputedStyle.marginRight,
1521 marginBottom = _getComputedStyle.marginBottom,
1522 marginLeft = _getComputedStyle.marginLeft; // We no longer take into account `margins` on the popper, and it can
1523 // cause bugs with positioning, so we'll warn the consumer
1524
1525
1526 if ([marginTop, marginRight, marginBottom, marginLeft].some(function (margin) {
1527 return parseFloat(margin);
1528 })) {
1529 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(' '));
1530 }
1531 }
1532
1533 runModifierEffects();
1534 return instance.update();
1535 },
1536 // Sync update – it will always be executed, even if not necessary. This
1537 // is useful for low frequency updates where sync behavior simplifies the
1538 // logic.
1539 // For high frequency updates (e.g. `resize` and `scroll` events), always
1540 // prefer the async Popper#update method
1541 forceUpdate: function forceUpdate() {
1542 if (isDestroyed) {
1543 return;
1544 }
1545
1546 var _state$elements = state.elements,
1547 reference = _state$elements.reference,
1548 popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
1549 // anymore
1550
1551 if (!areValidElements(reference, popper)) {
1552 if (process.env.NODE_ENV !== "production") {
1553 console.error(INVALID_ELEMENT_ERROR);
1554 }
1555
1556 return;
1557 } // Store the reference and popper rects to be read by modifiers
1558
1559
1560 state.rects = {
1561 reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
1562 popper: getLayoutRect(popper)
1563 }; // Modifiers have the ability to reset the current update cycle. The
1564 // most common use case for this is the `flip` modifier changing the
1565 // placement, which then needs to re-run all the modifiers, because the
1566 // logic was previously ran for the previous placement and is therefore
1567 // stale/incorrect
1568
1569 state.reset = false;
1570 state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
1571 // is filled with the initial data specified by the modifier. This means
1572 // it doesn't persist and is fresh on each update.
1573 // To ensure persistent data, use `${name}#persistent`
1574
1575 state.orderedModifiers.forEach(function (modifier) {
1576 return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
1577 });
1578 var __debug_loops__ = 0;
1579
1580 for (var index = 0; index < state.orderedModifiers.length; index++) {
1581 if (process.env.NODE_ENV !== "production") {
1582 __debug_loops__ += 1;
1583
1584 if (__debug_loops__ > 100) {
1585 console.error(INFINITE_LOOP_ERROR);
1586 break;
1587 }
1588 }
1589
1590 if (state.reset === true) {
1591 state.reset = false;
1592 index = -1;
1593 continue;
1594 }
1595
1596 var _state$orderedModifie = state.orderedModifiers[index],
1597 fn = _state$orderedModifie.fn,
1598 _state$orderedModifie2 = _state$orderedModifie.options,
1599 _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
1600 name = _state$orderedModifie.name;
1601
1602 if (typeof fn === 'function') {
1603 state = fn({
1604 state: state,
1605 options: _options,
1606 name: name,
1607 instance: instance
1608 }) || state;
1609 }
1610 }
1611 },
1612 // Async and optimistically optimized update – it will not be executed if
1613 // not necessary (debounced to run at most once-per-tick)
1614 update: debounce(function () {
1615 return new Promise(function (resolve) {
1616 instance.forceUpdate();
1617 resolve(state);
1618 });
1619 }),
1620 destroy: function destroy() {
1621 cleanupModifierEffects();
1622 isDestroyed = true;
1623 }
1624 };
1625
1626 if (!areValidElements(reference, popper)) {
1627 if (process.env.NODE_ENV !== "production") {
1628 console.error(INVALID_ELEMENT_ERROR);
1629 }
1630
1631 return instance;
1632 }
1633
1634 instance.setOptions(options).then(function (state) {
1635 if (!isDestroyed && options.onFirstUpdate) {
1636 options.onFirstUpdate(state);
1637 }
1638 }); // Modifiers have the ability to execute arbitrary code before the first
1639 // update cycle runs. They will be executed in the same order as the update
1640 // cycle. This is useful when a modifier adds some persistent data that
1641 // other modifiers need to use, but the modifier is run after the dependent
1642 // one.
1643
1644 function runModifierEffects() {
1645 state.orderedModifiers.forEach(function (_ref3) {
1646 var name = _ref3.name,
1647 _ref3$options = _ref3.options,
1648 options = _ref3$options === void 0 ? {} : _ref3$options,
1649 effect = _ref3.effect;
1650
1651 if (typeof effect === 'function') {
1652 var cleanupFn = effect({
1653 state: state,
1654 name: name,
1655 instance: instance,
1656 options: options
1657 });
1658
1659 var noopFn = function noopFn() {};
1660
1661 effectCleanupFns.push(cleanupFn || noopFn);
1662 }
1663 });
1664 }
1665
1666 function cleanupModifierEffects() {
1667 effectCleanupFns.forEach(function (fn) {
1668 return fn();
1669 });
1670 effectCleanupFns = [];
1671 }
1672
1673 return instance;
1674 };
1675}
1676
1677// For the common JS build we will turn this file into a bundle with no imports.
1678// This is b/c the Popper lib is all esm files, and would break in a common js only environment
1679const createPopper = popperGenerator({
1680 defaultModifiers: [
1681 hide$1,
1682 popperOffsets$1,
1683 computeStyles$1,
1684 eventListeners,
1685 offset$1,
1686 flip$1,
1687 preventOverflow$1,
1688 arrow$1,
1689 ],
1690});
1691
1692exports.createPopper = createPopper;
1693exports.placements = placements;