UNPKG

@base-ui-components/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

74 lines (73 loc) 2.75 kB
"use strict"; 'use client'; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTransitionStatus = useTransitionStatus; var React = _interopRequireWildcard(require("react")); var ReactDOM = _interopRequireWildcard(require("react-dom")); var _useIsoLayoutEffect = require("@base-ui-components/utils/useIsoLayoutEffect"); var _useAnimationFrame = require("@base-ui-components/utils/useAnimationFrame"); /** * Provides a status string for CSS animations. * @param open - a boolean that determines if the element is open. * @param enableIdleState - a boolean that enables the `'idle'` state between `'starting'` and `'ending'` */ function useTransitionStatus(open, enableIdleState = false, deferEndingState = false) { const [transitionStatus, setTransitionStatus] = React.useState(open && enableIdleState ? 'idle' : undefined); const [mounted, setMounted] = React.useState(open); if (open && !mounted) { setMounted(true); setTransitionStatus('starting'); } if (!open && mounted && transitionStatus !== 'ending' && !deferEndingState) { setTransitionStatus('ending'); } if (!open && !mounted && transitionStatus === 'ending') { setTransitionStatus(undefined); } (0, _useIsoLayoutEffect.useIsoLayoutEffect)(() => { if (!open && mounted && transitionStatus !== 'ending' && deferEndingState) { const frame = _useAnimationFrame.AnimationFrame.request(() => { setTransitionStatus('ending'); }); return () => { _useAnimationFrame.AnimationFrame.cancel(frame); }; } return undefined; }, [open, mounted, transitionStatus, deferEndingState]); (0, _useIsoLayoutEffect.useIsoLayoutEffect)(() => { if (!open || enableIdleState) { return undefined; } const frame = _useAnimationFrame.AnimationFrame.request(() => { ReactDOM.flushSync(() => { setTransitionStatus(undefined); }); }); return () => { _useAnimationFrame.AnimationFrame.cancel(frame); }; }, [enableIdleState, open]); (0, _useIsoLayoutEffect.useIsoLayoutEffect)(() => { if (!open || !enableIdleState) { return undefined; } if (open && mounted && transitionStatus !== 'idle') { setTransitionStatus('starting'); } const frame = _useAnimationFrame.AnimationFrame.request(() => { setTransitionStatus('idle'); }); return () => { _useAnimationFrame.AnimationFrame.cancel(frame); }; }, [enableIdleState, open, mounted, setTransitionStatus, transitionStatus]); return React.useMemo(() => ({ mounted, setMounted, transitionStatus }), [mounted, transitionStatus]); }