/**
 * External dependencies
 */

/**
 * Internal dependencies
 */

const POSITION_TO_PLACEMENT = {
  bottom: 'bottom',
  top: 'top',
  'middle left': 'left',
  'middle right': 'right',
  'bottom left': 'bottom-end',
  'bottom center': 'bottom',
  'bottom right': 'bottom-start',
  'top left': 'top-end',
  'top center': 'top',
  'top right': 'top-start',
  'middle left left': 'left',
  'middle left right': 'left',
  'middle left bottom': 'left-end',
  'middle left top': 'left-start',
  'middle right left': 'right',
  'middle right right': 'right',
  'middle right bottom': 'right-end',
  'middle right top': 'right-start',
  'bottom left left': 'bottom-end',
  'bottom left right': 'bottom-end',
  'bottom left bottom': 'bottom-end',
  'bottom left top': 'bottom-end',
  'bottom center left': 'bottom',
  'bottom center right': 'bottom',
  'bottom center bottom': 'bottom',
  'bottom center top': 'bottom',
  'bottom right left': 'bottom-start',
  'bottom right right': 'bottom-start',
  'bottom right bottom': 'bottom-start',
  'bottom right top': 'bottom-start',
  'top left left': 'top-end',
  'top left right': 'top-end',
  'top left bottom': 'top-end',
  'top left top': 'top-end',
  'top center left': 'top',
  'top center right': 'top',
  'top center bottom': 'top',
  'top center top': 'top',
  'top right left': 'top-start',
  'top right right': 'top-start',
  'top right bottom': 'top-start',
  'top right top': 'top-start',
  // `middle`/`middle center [corner?]` positions are associated to a fallback
  // `bottom` placement because there aren't any corresponding placement values.
  middle: 'bottom',
  'middle center': 'bottom',
  'middle center bottom': 'bottom',
  'middle center left': 'bottom',
  'middle center right': 'bottom',
  'middle center top': 'bottom'
};

/**
 * Converts the `Popover`'s legacy "position" prop to the new "placement" prop
 * (used by `floating-ui`).
 *
 * @param position The legacy position
 * @return The corresponding placement
 */
export const positionToPlacement = position => {
  var _POSITION_TO_PLACEMEN;
  return (_POSITION_TO_PLACEMEN = POSITION_TO_PLACEMENT[position]) !== null && _POSITION_TO_PLACEMEN !== void 0 ? _POSITION_TO_PLACEMEN : 'bottom';
};

/**
 * @typedef AnimationOrigin
 * @type {Object}
 * @property {number} originX A number between 0 and 1 (in CSS logical properties jargon, 0 is "start", 0.5 is "center", and 1 is "end")
 * @property {number} originY A number between 0 and 1 (0 is top, 0.5 is center, and 1 is bottom)
 */

const PLACEMENT_TO_ANIMATION_ORIGIN = {
  top: {
    originX: 0.5,
    originY: 1
  },
  // open from bottom, center
  'top-start': {
    originX: 0,
    originY: 1
  },
  // open from bottom, left
  'top-end': {
    originX: 1,
    originY: 1
  },
  // open from bottom, right
  right: {
    originX: 0,
    originY: 0.5
  },
  // open from middle, left
  'right-start': {
    originX: 0,
    originY: 0
  },
  // open from top, left
  'right-end': {
    originX: 0,
    originY: 1
  },
  // open from bottom, left
  bottom: {
    originX: 0.5,
    originY: 0
  },
  // open from top, center
  'bottom-start': {
    originX: 0,
    originY: 0
  },
  // open from top, left
  'bottom-end': {
    originX: 1,
    originY: 0
  },
  // open from top, right
  left: {
    originX: 1,
    originY: 0.5
  },
  // open from middle, right
  'left-start': {
    originX: 1,
    originY: 0
  },
  // open from top, right
  'left-end': {
    originX: 1,
    originY: 1
  },
  // open from bottom, right
  overlay: {
    originX: 0.5,
    originY: 0.5
  } // open from center, center
};

/**
 * Given the floating-ui `placement`, compute the framer-motion props for the
 * popover's entry animation.
 *
 * @param placement A placement string from floating ui
 * @return The object containing the motion props
 */
export const placementToMotionAnimationProps = placement => {
  const translateProp = placement.startsWith('top') || placement.startsWith('bottom') ? 'translateY' : 'translateX';
  const translateDirection = placement.startsWith('top') || placement.startsWith('left') ? 1 : -1;
  return {
    style: PLACEMENT_TO_ANIMATION_ORIGIN[placement],
    initial: {
      opacity: 0,
      scale: 0,
      [translateProp]: `${2 * translateDirection}em`
    },
    animate: {
      opacity: 1,
      scale: 1,
      [translateProp]: 0
    },
    transition: {
      duration: 0.1,
      ease: [0, 0, 0.2, 1]
    }
  };
};
function isTopBottom(anchorRef) {
  return !!anchorRef?.top;
}
function isRef(anchorRef) {
  return !!anchorRef?.current;
}
export const getReferenceElement = ({
  anchor,
  anchorRef,
  anchorRect,
  getAnchorRect,
  fallbackReferenceElement
}) => {
  var _referenceElement;
  let referenceElement = null;
  if (anchor) {
    referenceElement = anchor;
  } else if (isTopBottom(anchorRef)) {
    // Create a virtual element for the ref. The expectation is that
    // if anchorRef.top is defined, then anchorRef.bottom is defined too.
    // Seems to be used by the block toolbar, when multiple blocks are selected
    // (top and bottom blocks are used to calculate the resulting rect).
    referenceElement = {
      getBoundingClientRect() {
        const topRect = anchorRef.top.getBoundingClientRect();
        const bottomRect = anchorRef.bottom.getBoundingClientRect();
        return new window.DOMRect(topRect.x, topRect.y, topRect.width, bottomRect.bottom - topRect.top);
      }
    };
  } else if (isRef(anchorRef)) {
    // Standard React ref.
    referenceElement = anchorRef.current;
  } else if (anchorRef) {
    // If `anchorRef` holds directly the element's value (no `current` key)
    // This is a weird scenario and should be deprecated.
    referenceElement = anchorRef;
  } else if (anchorRect) {
    // Create a virtual element for the ref.
    referenceElement = {
      getBoundingClientRect() {
        return anchorRect;
      }
    };
  } else if (getAnchorRect) {
    // Create a virtual element for the ref.
    referenceElement = {
      getBoundingClientRect() {
        var _rect$x, _rect$y, _rect$width, _rect$height;
        const rect = getAnchorRect(fallbackReferenceElement);
        return new window.DOMRect((_rect$x = rect.x) !== null && _rect$x !== void 0 ? _rect$x : rect.left, (_rect$y = rect.y) !== null && _rect$y !== void 0 ? _rect$y : rect.top, (_rect$width = rect.width) !== null && _rect$width !== void 0 ? _rect$width : rect.right - rect.left, (_rect$height = rect.height) !== null && _rect$height !== void 0 ? _rect$height : rect.bottom - rect.top);
      }
    };
  } else if (fallbackReferenceElement) {
    // If no explicit ref is passed via props, fall back to
    // anchoring to the popover's parent node.
    referenceElement = fallbackReferenceElement.parentElement;
  }

  // Convert any `undefined` value to `null`.
  return (_referenceElement = referenceElement) !== null && _referenceElement !== void 0 ? _referenceElement : null;
};

/**
 * Computes the final coordinate that needs to be applied to the floating
 * element when applying transform inline styles, defaulting to `undefined`
 * if the provided value is `null` or `NaN`.
 *
 * @param c input coordinate (usually as returned from floating-ui)
 * @return The coordinate's value to be used for inline styles. An `undefined`
 *         return value means "no style set" for this coordinate.
 */
export const computePopoverPosition = c => c === null || Number.isNaN(c) ? undefined : Math.round(c);
//# sourceMappingURL=utils.js.map