{"version":3,"file":"usePresence.cjs","sources":["../../src/Presence/usePresence.ts"],"sourcesContent":["import type { Ref } from 'vue'\nimport { defaultWindow } from '@vueuse/core'\nimport { isClient } from '@vueuse/shared'\nimport { computed, nextTick, onUnmounted, ref, watch } from 'vue'\nimport { useStateMachine } from '@/shared'\n\nexport function usePresence(\n present: Ref,\n node: Ref,\n) {\n const stylesRef = ref({} as any)\n const prevAnimationNameRef = ref('none')\n const prevPresentRef = ref(present)\n const initialState = present.value ? 'mounted' : 'unmounted'\n let timeoutId: number | undefined\n const ownerWindow = node.value?.ownerDocument.defaultView ?? defaultWindow\n\n const { state, dispatch } = 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 const dispatchCustomEvent = (name: 'enter' | 'after-enter' | 'leave' | 'after-leave') => {\n // We only dispatch this event because CustomEvent is not available in Node18\n // https://github.com/unovue/reka-ui/issues/930\n if (isClient) {\n const customEvent = new CustomEvent(name, { bubbles: false, cancelable: false })\n node.value?.dispatchEvent(customEvent)\n }\n }\n\n watch(\n present,\n async (currentPresent, prevPresent) => {\n const hasPresentChanged = prevPresent !== currentPresent\n await nextTick()\n if (hasPresentChanged) {\n const prevAnimationName = prevAnimationNameRef.value\n const currentAnimationName = getAnimationName(node.value)\n\n if (currentPresent) {\n dispatch('MOUNT')\n dispatchCustomEvent('enter')\n if (currentAnimationName === 'none')\n dispatchCustomEvent('after-enter')\n }\n else if (\n currentAnimationName === 'none' || currentAnimationName === 'undefined'\n || stylesRef.value?.display === 'none'\n ) {\n // If there is no exit animation or the element is hidden, animations won't run\n // so we unmount instantly rv\n dispatch('UNMOUNT')\n dispatchCustomEvent('leave')\n dispatchCustomEvent('after-leave')\n }\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 if (prevPresent && isAnimating) {\n dispatch('ANIMATION_OUT')\n dispatchCustomEvent('leave')\n }\n else {\n dispatch('UNMOUNT')\n dispatchCustomEvent('after-leave')\n }\n }\n }\n },\n { immediate: true },\n )\n\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(node.value)\n const isCurrentAnimation = currentAnimationName.includes(\n event.animationName,\n )\n const directionName = state.value === 'mounted' ? 'enter' : 'leave'\n if (event.target === node.value && isCurrentAnimation) {\n dispatchCustomEvent(`after-${directionName}`)\n dispatch('ANIMATION_END')\n\n if (!prevPresentRef.value) {\n const currentFillMode = node.value.style.animationFillMode\n node.value.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.value?.style.animationFillMode === 'forwards') {\n node.value.style.animationFillMode = currentFillMode\n }\n })\n }\n }\n // if no animation, immediately trigger 'ANIMATION_END'\n if (event.target === node.value && currentAnimationName === 'none')\n dispatch('ANIMATION_END')\n }\n const handleAnimationStart = (event: AnimationEvent) => {\n if (event.target === node.value) {\n // if animation occurred, store its name as the previous animation.\n prevAnimationNameRef.value = getAnimationName(node.value)\n }\n }\n\n const watcher = watch(\n node,\n (newNode, oldNode) => {\n if (newNode) {\n stylesRef.value = getComputedStyle(newNode)\n newNode.addEventListener('animationstart', handleAnimationStart)\n newNode.addEventListener('animationcancel', handleAnimationEnd)\n newNode.addEventListener('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 dispatch('ANIMATION_END')\n\n if (timeoutId !== undefined)\n ownerWindow?.clearTimeout(timeoutId)\n oldNode?.removeEventListener('animationstart', handleAnimationStart)\n oldNode?.removeEventListener('animationcancel', handleAnimationEnd)\n oldNode?.removeEventListener('animationend', handleAnimationEnd)\n }\n },\n { immediate: true },\n )\n\n const stateWatcher = watch(state, () => {\n const currentAnimationName = getAnimationName(node.value)\n prevAnimationNameRef.value\n = state.value === 'mounted' ? currentAnimationName : 'none'\n })\n\n onUnmounted(() => {\n watcher()\n stateWatcher()\n })\n\n const isPresent = computed(() =>\n ['mounted', 'unmountSuspended'].includes(state.value),\n )\n\n return {\n isPresent,\n }\n}\n\nfunction getAnimationName(node?: HTMLElement) {\n return node ? getComputedStyle(node).animationName || 'none' : 'none'\n}\n"],"names":["ref","defaultWindow","useStateMachine","isClient","watch","nextTick","onUnmounted","computed"],"mappings":"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"}