UNPKG

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