var $fnLeV$react = require("react"); var $fnLeV$reactdom = require("react-dom"); var $fnLeV$radixuireactcomposerefs = require("@radix-ui/react-compose-refs"); var $fnLeV$radixuireactuselayouteffect = require("@radix-ui/react-use-layout-effect"); function $parcel$export(e, n, v, s) { Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true}); } $parcel$export(module.exports, "Presence", () => $a2fa0214bb2735a1$export$99c2b779aa4e8b8b); function $8f63844556d0d3cd$export$3e6543de14f8614f(initialState, machine) { return $fnLeV$react.useReducer((state, event)=>{ const nextState = machine[state][event]; return nextState !== null && nextState !== void 0 ? nextState : state; }, initialState); } const $a2fa0214bb2735a1$export$99c2b779aa4e8b8b = (props)=>{ const { present: present , children: children } = props; const presence = $a2fa0214bb2735a1$var$usePresence(present); const child = typeof children === 'function' ? children({ present: presence.isPresent }) : $fnLeV$react.Children.only(children); const ref = $fnLeV$radixuireactcomposerefs.useComposedRefs(presence.ref, child.ref); const forceMount = typeof children === 'function'; return forceMount || presence.isPresent ? /*#__PURE__*/ $fnLeV$react.cloneElement(child, { ref: ref }) : null; }; $a2fa0214bb2735a1$export$99c2b779aa4e8b8b.displayName = 'Presence'; /* ------------------------------------------------------------------------------------------------- * usePresence * -----------------------------------------------------------------------------------------------*/ function $a2fa0214bb2735a1$var$usePresence(present) { const [node1, setNode] = $fnLeV$react.useState(); const stylesRef = $fnLeV$react.useRef({}); const prevPresentRef = $fnLeV$react.useRef(present); const prevAnimationNameRef = $fnLeV$react.useRef('none'); const initialState = present ? 'mounted' : 'unmounted'; const [state, send] = $8f63844556d0d3cd$export$3e6543de14f8614f(initialState, { mounted: { UNMOUNT: 'unmounted', ANIMATION_OUT: 'unmountSuspended' }, unmountSuspended: { MOUNT: 'mounted', ANIMATION_END: 'unmounted' }, unmounted: { MOUNT: 'mounted' } }); $fnLeV$react.useEffect(()=>{ const currentAnimationName = $a2fa0214bb2735a1$var$getAnimationName(stylesRef.current); prevAnimationNameRef.current = state === 'mounted' ? currentAnimationName : 'none'; }, [ state ]); $fnLeV$radixuireactuselayouteffect.useLayoutEffect(()=>{ const styles = stylesRef.current; const wasPresent = prevPresentRef.current; const hasPresentChanged = wasPresent !== present; if (hasPresentChanged) { const prevAnimationName = prevAnimationNameRef.current; const currentAnimationName = $a2fa0214bb2735a1$var$getAnimationName(styles); if (present) send('MOUNT'); else if (currentAnimationName === 'none' || (styles === null || styles === void 0 ? void 0 : styles.display) === 'none') // If there is no exit animation or the element is hidden, animations won't run // so we unmount instantly send('UNMOUNT'); else { /** * When `present` changes to `false`, we check changes to animation-name to * determine whether an animation has started. We chose this approach (reading * computed styles) because there is no `animationrun` event and `animationstart` * fires after `animation-delay` has expired which would be too late. */ const isAnimating = prevAnimationName !== currentAnimationName; if (wasPresent && isAnimating) send('ANIMATION_OUT'); else send('UNMOUNT'); } prevPresentRef.current = present; } }, [ present, send ]); $fnLeV$radixuireactuselayouteffect.useLayoutEffect(()=>{ if (node1) { /** * Triggering an ANIMATION_OUT during an ANIMATION_IN will fire an `animationcancel` * event for ANIMATION_IN after we have entered `unmountSuspended` state. So, we * make sure we only trigger ANIMATION_END for the currently active animation. */ const handleAnimationEnd = (event)=>{ const currentAnimationName = $a2fa0214bb2735a1$var$getAnimationName(stylesRef.current); const isCurrentAnimation = currentAnimationName.includes(event.animationName); if (event.target === node1 && isCurrentAnimation) // With React 18 concurrency this update is applied // a frame after the animation ends, creating a flash of visible content. // By manually flushing we ensure they sync within a frame, removing the flash. $fnLeV$reactdom.flushSync(()=>send('ANIMATION_END') ); }; const handleAnimationStart = (event)=>{ if (event.target === node1) // if animation occurred, store its name as the previous animation. prevAnimationNameRef.current = $a2fa0214bb2735a1$var$getAnimationName(stylesRef.current); }; node1.addEventListener('animationstart', handleAnimationStart); node1.addEventListener('animationcancel', handleAnimationEnd); node1.addEventListener('animationend', handleAnimationEnd); return ()=>{ node1.removeEventListener('animationstart', handleAnimationStart); node1.removeEventListener('animationcancel', handleAnimationEnd); node1.removeEventListener('animationend', handleAnimationEnd); }; } else // Transition to the unmounted state if the node is removed prematurely. // We avoid doing so during cleanup as the node may change but still exist. send('ANIMATION_END'); }, [ node1, send ]); return { isPresent: [ 'mounted', 'unmountSuspended' ].includes(state), ref: $fnLeV$react.useCallback((node)=>{ if (node) stylesRef.current = getComputedStyle(node); setNode(node); }, []) }; } /* -----------------------------------------------------------------------------------------------*/ function $a2fa0214bb2735a1$var$getAnimationName(styles) { return (styles === null || styles === void 0 ? void 0 : styles.animationName) || 'none'; } //# sourceMappingURL=index.js.map