@wordpress/components
Version:
UI components for WordPress.
75 lines (72 loc) • 2.86 kB
JavaScript
;
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