{
  "version": 3,
  "sources": ["../src/presence.tsx", "../src/use-state-machine.tsx"],
  "sourcesContent": ["import * as React from 'react';\nimport { useComposedRefs } from '@radix-ui/react-compose-refs';\nimport { useLayoutEffect } from '@radix-ui/react-use-layout-effect';\nimport { useStateMachine } from './use-state-machine';\n\ninterface PresenceProps {\n  children: React.ReactElement | ((props: { present: boolean }) => React.ReactElement);\n  present: boolean;\n}\n\nconst Presence: React.FC<PresenceProps> = (props) => {\n  const { present, children } = props;\n  const presence = usePresence(present);\n\n  const child = (\n    typeof children === 'function'\n      ? children({ present: presence.isPresent })\n      : React.Children.only(children)\n  ) as React.ReactElement<{ ref?: React.Ref<HTMLElement> }>;\n\n  const ref = useComposedRefs(presence.ref, getElementRef(child));\n  const forceMount = typeof children === 'function';\n  return forceMount || presence.isPresent ? React.cloneElement(child, { ref }) : null;\n};\n\nPresence.displayName = 'Presence';\n\n/* -------------------------------------------------------------------------------------------------\n * usePresence\n * -----------------------------------------------------------------------------------------------*/\n\nfunction usePresence(present: boolean) {\n  const [node, setNode] = React.useState<HTMLElement>();\n  const stylesRef = React.useRef<CSSStyleDeclaration | null>(null);\n  const prevPresentRef = React.useRef(present);\n  const prevAnimationNameRef = React.useRef<string>('none');\n  const initialState = present ? 'mounted' : 'unmounted';\n  const [state, send] = useStateMachine(initialState, {\n    mounted: {\n      UNMOUNT: 'unmounted',\n      ANIMATION_OUT: 'unmountSuspended',\n    },\n    unmountSuspended: {\n      MOUNT: 'mounted',\n      ANIMATION_END: 'unmounted',\n    },\n    unmounted: {\n      MOUNT: 'mounted',\n    },\n  });\n\n  React.useEffect(() => {\n    const currentAnimationName = getAnimationName(stylesRef.current);\n    prevAnimationNameRef.current = state === 'mounted' ? currentAnimationName : 'none';\n  }, [state]);\n\n  useLayoutEffect(() => {\n    const styles = stylesRef.current;\n    const wasPresent = prevPresentRef.current;\n    const hasPresentChanged = wasPresent !== present;\n\n    if (hasPresentChanged) {\n      const prevAnimationName = prevAnimationNameRef.current;\n      const currentAnimationName = getAnimationName(styles);\n\n      if (present) {\n        send('MOUNT');\n      } else if (currentAnimationName === 'none' || styles?.display === 'none') {\n        // If there is no exit animation or the element is hidden, animations won't run\n        // so we unmount instantly\n        send('UNMOUNT');\n      } else {\n        /**\n         * When `present` changes to `false`, we check changes to animation-name to\n         * determine whether an animation has started. We chose this approach (reading\n         * computed styles) because there is no `animationrun` event and `animationstart`\n         * fires after `animation-delay` has expired which would be too late.\n         */\n        const isAnimating = prevAnimationName !== currentAnimationName;\n\n        if (wasPresent && isAnimating) {\n          send('ANIMATION_OUT');\n        } else {\n          send('UNMOUNT');\n        }\n      }\n\n      prevPresentRef.current = present;\n    }\n  }, [present, send]);\n\n  useLayoutEffect(() => {\n    if (node) {\n      let timeoutId: number;\n      const ownerWindow = node.ownerDocument.defaultView ?? window;\n      /**\n       * Triggering an ANIMATION_OUT during an ANIMATION_IN will fire an `animationcancel`\n       * event for ANIMATION_IN after we have entered `unmountSuspended` state. So, we\n       * make sure we only trigger ANIMATION_END for the currently active animation.\n       */\n      const handleAnimationEnd = (event: AnimationEvent) => {\n        const currentAnimationName = getAnimationName(stylesRef.current);\n        // The event.animationName is unescaped for CSS syntax,\n        // so we need to escape it to compare with the animationName computed from the style.\n        const isCurrentAnimation = currentAnimationName.includes(CSS.escape(event.animationName));\n        if (event.target === node && isCurrentAnimation) {\n          // With React 18 concurrency this update is applied a frame after the\n          // animation ends, creating a flash of visible content. By setting the\n          // animation fill mode to \"forwards\", we force the node to keep the\n          // styles of the last keyframe, removing the flash.\n          //\n          // Previously we flushed the update via ReactDom.flushSync, but with\n          // exit animations this resulted in the node being removed from the\n          // DOM before the synthetic animationEnd event was dispatched, meaning\n          // user-provided event handlers would not be called.\n          // https://github.com/radix-ui/primitives/pull/1849\n          send('ANIMATION_END');\n          if (!prevPresentRef.current) {\n            const currentFillMode = node.style.animationFillMode;\n            node.style.animationFillMode = 'forwards';\n            // Reset the style after the node had time to unmount (for cases\n            // where the component chooses not to unmount). Doing this any\n            // sooner than `setTimeout` (e.g. with `requestAnimationFrame`)\n            // still causes a flash.\n            timeoutId = ownerWindow.setTimeout(() => {\n              if (node.style.animationFillMode === 'forwards') {\n                node.style.animationFillMode = currentFillMode;\n              }\n            });\n          }\n        }\n      };\n      const handleAnimationStart = (event: AnimationEvent) => {\n        if (event.target === node) {\n          // if animation occurred, store its name as the previous animation.\n          prevAnimationNameRef.current = getAnimationName(stylesRef.current);\n        }\n      };\n      node.addEventListener('animationstart', handleAnimationStart);\n      node.addEventListener('animationcancel', handleAnimationEnd);\n      node.addEventListener('animationend', handleAnimationEnd);\n      return () => {\n        ownerWindow.clearTimeout(timeoutId);\n        node.removeEventListener('animationstart', handleAnimationStart);\n        node.removeEventListener('animationcancel', handleAnimationEnd);\n        node.removeEventListener('animationend', handleAnimationEnd);\n      };\n    } else {\n      // Transition to the unmounted state if the node is removed prematurely.\n      // We avoid doing so during cleanup as the node may change but still exist.\n      send('ANIMATION_END');\n    }\n  }, [node, send]);\n\n  return {\n    isPresent: ['mounted', 'unmountSuspended'].includes(state),\n    ref: React.useCallback((node: HTMLElement) => {\n      stylesRef.current = node ? getComputedStyle(node) : null;\n      setNode(node);\n    }, []),\n  };\n}\n\n/* -----------------------------------------------------------------------------------------------*/\n\nfunction getAnimationName(styles: CSSStyleDeclaration | null) {\n  return styles?.animationName || 'none';\n}\n\n// Before React 19 accessing `element.props.ref` will throw a warning and suggest using `element.ref`\n// After React 19 accessing `element.ref` does the opposite.\n// https://github.com/facebook/react/pull/28348\n//\n// Access the ref using the method that doesn't yield a warning.\nfunction getElementRef(element: React.ReactElement<{ ref?: React.Ref<unknown> }>) {\n  // React <=18 in DEV\n  let getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get;\n  let mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n  if (mayWarn) {\n    return (element as any).ref;\n  }\n\n  // React 19 in DEV\n  getter = Object.getOwnPropertyDescriptor(element, 'ref')?.get;\n  mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n  if (mayWarn) {\n    return element.props.ref;\n  }\n\n  // Not DEV\n  return element.props.ref || (element as any).ref;\n}\n\nconst Root = Presence;\n\nexport {\n  Presence,\n  //\n  Root,\n};\nexport type { PresenceProps };\n", "import * as React from 'react';\n\ntype Machine<S> = { [k: string]: { [k: string]: S } };\ntype MachineState<T> = keyof T;\ntype MachineEvent<T> = keyof UnionToIntersection<T[keyof T]>;\n\n// \uD83E\uDD2F https://fettblog.eu/typescript-union-to-intersection/\ntype UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any\n  ? R\n  : never;\n\nexport function useStateMachine<M>(\n  initialState: MachineState<M>,\n  machine: M & Machine<MachineState<M>>\n) {\n  return React.useReducer((state: MachineState<M>, event: MachineEvent<M>): MachineState<M> => {\n    const nextState = (machine[state] as any)[event];\n    return nextState ?? state;\n  }, initialState);\n}\n"],
  "mappings": "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",
  "names": ["React", "node"]
}
