Skip to content

Commit

Permalink
fix(Presence): ensure onAnimationEnd when closing (#1471)
Browse files Browse the repository at this point in the history
(from radix-ui)
  • Loading branch information
sadeghbarati authored Dec 4, 2024
1 parent b4def6f commit 4a0ad49
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions packages/radix-vue/src/Presence/usePresence.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { type Ref, computed, nextTick, onUnmounted, ref, watch } from 'vue'
import { useStateMachine } from '@/shared'
import { isClient } from '@vueuse/shared'
import { defaultWindow } from '@vueuse/core'

export function usePresence(
present: Ref<boolean>,
node: Ref<HTMLElement | undefined>,
) {
const stylesRef = ref<CSSStyleDeclaration>({} as any)
const prevAnimationNameRef = ref<string>('none')
const prevPresentRef = ref(present)
const initialState = present.value ? 'mounted' : 'unmounted'
let timeoutId: number | undefined
const ownerWindow = node.value?.ownerDocument.defaultView ?? defaultWindow

const { state, dispatch } = useStateMachine(initialState, {
mounted: {
Expand Down Expand Up @@ -94,6 +98,20 @@ export function usePresence(
if (event.target === node.value && isCurrentAnimation) {
dispatchCustomEvent(`after-${directionName}`)
dispatch('ANIMATION_END')

if (!prevPresentRef.value) {
const currentFillMode = node.value.style.animationFillMode
node.value.style.animationFillMode = 'forwards'
// Reset the style after the node had time to unmount (for cases
// where the component chooses not to unmount). Doing this any
// sooner than `setTimeout` (e.g. with `requestAnimationFrame`)
// still causes a flash.
timeoutId = ownerWindow?.setTimeout(() => {
if (node.value?.style.animationFillMode === 'forwards') {
node.value.style.animationFillMode = currentFillMode
}
})
}
}
// if no animation, immediately trigger 'ANIMATION_END'
if (event.target === node.value && currentAnimationName === 'none')
Expand All @@ -120,6 +138,7 @@ export function usePresence(
// We avoid doing so during cleanup as the node may change but still exist.
dispatch('ANIMATION_END')

ownerWindow?.clearTimeout(timeoutId)
oldNode?.removeEventListener('animationstart', handleAnimationStart)
oldNode?.removeEventListener('animationcancel', handleAnimationEnd)
oldNode?.removeEventListener('animationend', handleAnimationEnd)
Expand Down

0 comments on commit 4a0ad49

Please sign in to comment.