import { useCallback, useMemo, useRef } from 'react'; import hasClass from 'dom-helpers/hasClass'; import { useBootstrapPrefix } from './ThemeProvider'; function getMargins(element) { var styles = window.getComputedStyle(element); var top = parseFloat(styles.marginTop) || 0; var right = parseFloat(styles.marginRight) || 0; var bottom = parseFloat(styles.marginBottom) || 0; var left = parseFloat(styles.marginLeft) || 0; return { top: top, right: right, bottom: bottom, left: left }; } export default function usePopperMarginModifiers() { var overlayRef = useRef(null); var margins = useRef(null); var arrowMargins = useRef(null); var popoverClass = useBootstrapPrefix(undefined, 'popover'); var dropdownMenuClass = useBootstrapPrefix(undefined, 'dropdown-menu'); var callback = useCallback(function (overlay) { if (!overlay || !(hasClass(overlay, popoverClass) || hasClass(overlay, dropdownMenuClass))) return; margins.current = getMargins(overlay); overlay.style.margin = '0'; overlayRef.current = overlay; }, [popoverClass, dropdownMenuClass]); var offset = useMemo(function () { return { name: 'offset', options: { offset: function offset(_ref) { var placement = _ref.placement; if (!margins.current) return [0, 0]; var _margins$current = margins.current, top = _margins$current.top, left = _margins$current.left, bottom = _margins$current.bottom, right = _margins$current.right; switch (placement.split('-')[0]) { case 'top': return [0, bottom]; case 'left': return [0, right]; case 'bottom': return [0, top]; case 'right': return [0, left]; default: return [0, 0]; } } } }; }, [margins]); var arrow = useMemo(function () { return { name: 'arrow', options: { padding: function padding() { // The options here are used for Popper 2.8.4 and up. // For earlier version, padding is handled in popoverArrowMargins below. if (!arrowMargins.current) { return 0; } var _arrowMargins$current = arrowMargins.current, top = _arrowMargins$current.top, right = _arrowMargins$current.right; var padding = top || right; return { top: padding, left: padding, right: padding, bottom: padding }; } } }; }, [arrowMargins]); // Converts popover arrow margin to arrow modifier padding var popoverArrowMargins = useMemo(function () { return { name: 'popoverArrowMargins', enabled: true, phase: 'main', requiresIfExists: ['arrow'], effect: function effect(_ref2) { var state = _ref2.state; if (!overlayRef.current || !state.elements.arrow || !hasClass(overlayRef.current, popoverClass)) { return undefined; } if (state.modifiersData['arrow#persistent']) { // @popperjs/core <= 2.8.3 uses arrow#persistent to pass padding to arrow modifier. var _getMargins = getMargins(state.elements.arrow), top = _getMargins.top, right = _getMargins.right; var padding = top || right; state.modifiersData['arrow#persistent'].padding = { top: padding, left: padding, right: padding, bottom: padding }; } else { // @popperjs/core >= 2.8.4 gets the padding from the arrow modifier options, // so we'll get the margins here, and let the arrow modifier above pass // it to popper. arrowMargins.current = getMargins(state.elements.arrow); } state.elements.arrow.style.margin = '0'; return function () { if (state.elements.arrow) state.elements.arrow.style.margin = ''; }; } }; }, [popoverClass]); return [callback, [offset, arrow, popoverArrowMargins]]; }