"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useModalExitAnimation = useModalExitAnimation;
var _compose = require("@wordpress/compose");
var _element = require("@wordpress/element");
var _utils = require("../utils");
var _warning = _interopRequireDefault(require("@wordpress/warning"));
/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

// Animation duration (ms) extracted to JS in order to be used on a setTimeout.
const FRAME_ANIMATION_DURATION = _utils.CONFIG.transitionDuration;
const FRAME_ANIMATION_DURATION_NUMBER = Number.parseInt(_utils.CONFIG.transitionDuration);
const EXIT_ANIMATION_NAME = 'components-modal__disappear-animation';
function useModalExitAnimation() {
  const frameRef = (0, _element.useRef)();
  const [isAnimatingOut, setIsAnimatingOut] = (0, _element.useState)(false);
  const isReducedMotion = (0, _compose.useReducedMotion)();
  const closeModal = (0, _element.useCallback)(() => new Promise(closeModalResolve => {
    // Grab a "stable" reference of the frame element, since
    // the value held by the react ref might change at runtime.
    const frameEl = frameRef.current;
    if (isReducedMotion) {
      closeModalResolve();
      return;
    }
    if (!frameEl) {
      globalThis.SCRIPT_DEBUG === true ? (0, _warning.default)("wp.components.Modal: the Modal component can't be closed with an exit animation because of a missing reference to the modal frame element.") : void 0;
      closeModalResolve();
      return;
    }
    let handleAnimationEnd;
    const startAnimation = () => new Promise(animationResolve => {
      handleAnimationEnd = e => {
        if (e.animationName === EXIT_ANIMATION_NAME) {
          animationResolve();
        }
      };
      frameEl.addEventListener('animationend', handleAnimationEnd);
      setIsAnimatingOut(true);
    });
    const animationTimeout = () => new Promise(timeoutResolve => {
      setTimeout(() => timeoutResolve(),
      // Allow an extra 20% of the animation duration for the
      // animationend event to fire, in case the animation frame is
      // slightly delayes by some other events in the event loop.
      FRAME_ANIMATION_DURATION_NUMBER * 1.2);
    });
    Promise.race([startAnimation(), animationTimeout()]).then(() => {
      if (handleAnimationEnd) {
        frameEl.removeEventListener('animationend', handleAnimationEnd);
      }
      setIsAnimatingOut(false);
      closeModalResolve();
    });
  }), [isReducedMotion]);
  return {
    overlayClassname: isAnimatingOut ? 'is-animating-out' : undefined,
    frameRef,
    frameStyle: {
      '--modal-frame-animation-duration': `${FRAME_ANIMATION_DURATION}`
    },
    closeModal
  };
}
//# sourceMappingURL=use-modal-exit-animation.js.map