index.mjs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import {Children as $iqq3r$Children, cloneElement as $iqq3r$cloneElement, useState as $iqq3r$useState, useRef as $iqq3r$useRef, useEffect as $iqq3r$useEffect, useCallback as $iqq3r$useCallback, useReducer as $iqq3r$useReducer} from "react";
  2. import {flushSync as $iqq3r$flushSync} from "react-dom";
  3. import {useComposedRefs as $iqq3r$useComposedRefs} from "@radix-ui/react-compose-refs";
  4. import {useLayoutEffect as $iqq3r$useLayoutEffect} from "@radix-ui/react-use-layout-effect";
  5. function $fe963b355347cc68$export$3e6543de14f8614f(initialState, machine) {
  6. return $iqq3r$useReducer((state, event)=>{
  7. const nextState = machine[state][event];
  8. return nextState !== null && nextState !== void 0 ? nextState : state;
  9. }, initialState);
  10. }
  11. const $921a889cee6df7e8$export$99c2b779aa4e8b8b = (props)=>{
  12. const { present: present , children: children } = props;
  13. const presence = $921a889cee6df7e8$var$usePresence(present);
  14. const child = typeof children === 'function' ? children({
  15. present: presence.isPresent
  16. }) : $iqq3r$Children.only(children);
  17. const ref = $iqq3r$useComposedRefs(presence.ref, child.ref);
  18. const forceMount = typeof children === 'function';
  19. return forceMount || presence.isPresent ? /*#__PURE__*/ $iqq3r$cloneElement(child, {
  20. ref: ref
  21. }) : null;
  22. };
  23. $921a889cee6df7e8$export$99c2b779aa4e8b8b.displayName = 'Presence';
  24. /* -------------------------------------------------------------------------------------------------
  25. * usePresence
  26. * -----------------------------------------------------------------------------------------------*/ function $921a889cee6df7e8$var$usePresence(present) {
  27. const [node1, setNode] = $iqq3r$useState();
  28. const stylesRef = $iqq3r$useRef({});
  29. const prevPresentRef = $iqq3r$useRef(present);
  30. const prevAnimationNameRef = $iqq3r$useRef('none');
  31. const initialState = present ? 'mounted' : 'unmounted';
  32. const [state, send] = $fe963b355347cc68$export$3e6543de14f8614f(initialState, {
  33. mounted: {
  34. UNMOUNT: 'unmounted',
  35. ANIMATION_OUT: 'unmountSuspended'
  36. },
  37. unmountSuspended: {
  38. MOUNT: 'mounted',
  39. ANIMATION_END: 'unmounted'
  40. },
  41. unmounted: {
  42. MOUNT: 'mounted'
  43. }
  44. });
  45. $iqq3r$useEffect(()=>{
  46. const currentAnimationName = $921a889cee6df7e8$var$getAnimationName(stylesRef.current);
  47. prevAnimationNameRef.current = state === 'mounted' ? currentAnimationName : 'none';
  48. }, [
  49. state
  50. ]);
  51. $iqq3r$useLayoutEffect(()=>{
  52. const styles = stylesRef.current;
  53. const wasPresent = prevPresentRef.current;
  54. const hasPresentChanged = wasPresent !== present;
  55. if (hasPresentChanged) {
  56. const prevAnimationName = prevAnimationNameRef.current;
  57. const currentAnimationName = $921a889cee6df7e8$var$getAnimationName(styles);
  58. if (present) send('MOUNT');
  59. 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
  60. // so we unmount instantly
  61. send('UNMOUNT');
  62. else {
  63. /**
  64. * When `present` changes to `false`, we check changes to animation-name to
  65. * determine whether an animation has started. We chose this approach (reading
  66. * computed styles) because there is no `animationrun` event and `animationstart`
  67. * fires after `animation-delay` has expired which would be too late.
  68. */ const isAnimating = prevAnimationName !== currentAnimationName;
  69. if (wasPresent && isAnimating) send('ANIMATION_OUT');
  70. else send('UNMOUNT');
  71. }
  72. prevPresentRef.current = present;
  73. }
  74. }, [
  75. present,
  76. send
  77. ]);
  78. $iqq3r$useLayoutEffect(()=>{
  79. if (node1) {
  80. /**
  81. * Triggering an ANIMATION_OUT during an ANIMATION_IN will fire an `animationcancel`
  82. * event for ANIMATION_IN after we have entered `unmountSuspended` state. So, we
  83. * make sure we only trigger ANIMATION_END for the currently active animation.
  84. */ const handleAnimationEnd = (event)=>{
  85. const currentAnimationName = $921a889cee6df7e8$var$getAnimationName(stylesRef.current);
  86. const isCurrentAnimation = currentAnimationName.includes(event.animationName);
  87. if (event.target === node1 && isCurrentAnimation) // With React 18 concurrency this update is applied
  88. // a frame after the animation ends, creating a flash of visible content.
  89. // By manually flushing we ensure they sync within a frame, removing the flash.
  90. $iqq3r$flushSync(()=>send('ANIMATION_END')
  91. );
  92. };
  93. const handleAnimationStart = (event)=>{
  94. if (event.target === node1) // if animation occurred, store its name as the previous animation.
  95. prevAnimationNameRef.current = $921a889cee6df7e8$var$getAnimationName(stylesRef.current);
  96. };
  97. node1.addEventListener('animationstart', handleAnimationStart);
  98. node1.addEventListener('animationcancel', handleAnimationEnd);
  99. node1.addEventListener('animationend', handleAnimationEnd);
  100. return ()=>{
  101. node1.removeEventListener('animationstart', handleAnimationStart);
  102. node1.removeEventListener('animationcancel', handleAnimationEnd);
  103. node1.removeEventListener('animationend', handleAnimationEnd);
  104. };
  105. } else // Transition to the unmounted state if the node is removed prematurely.
  106. // We avoid doing so during cleanup as the node may change but still exist.
  107. send('ANIMATION_END');
  108. }, [
  109. node1,
  110. send
  111. ]);
  112. return {
  113. isPresent: [
  114. 'mounted',
  115. 'unmountSuspended'
  116. ].includes(state),
  117. ref: $iqq3r$useCallback((node)=>{
  118. if (node) stylesRef.current = getComputedStyle(node);
  119. setNode(node);
  120. }, [])
  121. };
  122. }
  123. /* -----------------------------------------------------------------------------------------------*/ function $921a889cee6df7e8$var$getAnimationName(styles) {
  124. return (styles === null || styles === void 0 ? void 0 : styles.animationName) || 'none';
  125. }
  126. export {$921a889cee6df7e8$export$99c2b779aa4e8b8b as Presence};
  127. //# sourceMappingURL=index.mjs.map