UNPKG

@navikt/ds-react

Version:

React components from the Norwegian Labour and Welfare Administration.

67 lines (60 loc) 2.13 kB
"use client"; import React, { useEffect } from "react"; import { useAnimationsFinished } from "./useAnimationsFinished"; import { useEventCallback } from "./useEventCallback"; import { useValueAsRef } from "./useValueAsRef"; interface useOpenChangeAnimationCompleteParameters { /** * Enable / disable the effect. Disabled => no animation tracking / callback. * @default true */ enabled?: boolean; /** * Current open state (e.g. popover open). When this flips we wait for any * associated CSS/Web animations on `ref` to finish before firing `onComplete`. */ open?: boolean; /** * Element whose animations/transition we observe. Should be stable while the * open/close animation runs (typically the root animated node). */ ref?: React.RefObject<HTMLElement | null>; /** * Called exactly once per open-change cycle after animations finish OR * immediately if animations are disabled / unsupported. */ onComplete: () => void; } /** * Waits for the element's current Web Animations / CSS transitions to finish after an * `open` state change, then invokes `onComplete`. Guards against race conditions by * comparing the `open` value captured at scheduling time with the latest `open` via ref; * if they differ (state flipped again mid‑animation) the callback is skipped. */ export function useOpenChangeAnimationComplete( parameters: useOpenChangeAnimationCompleteParameters, ) { const { enabled = true, open, ref = null, onComplete: onCompleteParam, } = parameters; const openRef = useValueAsRef(open); const onComplete = useEventCallback(onCompleteParam); const runOnceAnimationsFinish = useAnimationsFinished(ref, open); useEffect(() => { if (!enabled) { return; } /* * Schedule completion once the *current* set of animations settle. If during * that wait `open` toggles again, skip to avoid firing for an outdated cycle. */ runOnceAnimationsFinish(() => { if (open === openRef.current) { onComplete(); } }); }, [enabled, open, onComplete, runOnceAnimationsFinish, openRef]); }