From b7f9efd6c11ca399f81027838cd328921aefc836 Mon Sep 17 00:00:00 2001 From: inokawa <48897392+inokawa@users.noreply.github.com> Date: Fri, 25 Nov 2022 02:40:35 +0900 Subject: [PATCH] Change end method to waitFor and support waiting reverseFinish --- src/core/waapi.ts | 21 ++++++++++++++++++--- src/react/hooks/useAnimation.ts | 8 +++++--- src/react/hooks/useAnimationFunction.ts | 10 +++++++--- src/react/hooks/useTransitionAnimation.ts | 2 +- stories/hooks/useAnimation.stories.tsx | 12 ++++++------ 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/core/waapi.ts b/src/core/waapi.ts index e11a6a5..2dfc21c 100644 --- a/src/core/waapi.ts +++ b/src/core/waapi.ts @@ -1,5 +1,5 @@ import type { CSSProperties } from "react"; -import { getKeys, getStyle, noop, toArray, uniqBy } from "./utils"; +import { getKeys, getStyle, toArray, uniqBy } from "./utils"; export type AnimatableCSSProperties = Omit< CSSProperties, @@ -125,7 +125,22 @@ export const _setRate = ( typeof arg === "function" ? arg(animation.playbackRate) : arg ); }; -export const _end = (animation: Animation | undefined) => { + +export type WaitingAnimationEventName = "finish" | "reverseFinish"; +export const _waitFor = ( + animation: Animation | undefined, + name: WaitingAnimationEventName +): Promise => { if (!animation) return Promise.resolve(); - return animation.finished.then(noop); + + return new Promise((resolve) => { + animation.onfinish = () => { + if ( + (name === "finish" && animation.playbackRate > 0) || + (name === "reverseFinish" && animation.playbackRate < 0) + ) { + resolve(); + } + }; + }); }; diff --git a/src/react/hooks/useAnimation.ts b/src/react/hooks/useAnimation.ts index a98c83e..de30c74 100644 --- a/src/react/hooks/useAnimation.ts +++ b/src/react/hooks/useAnimation.ts @@ -10,13 +10,14 @@ import { ReverseOptions, TypedKeyframe, _cancel, - _end, + _waitFor, _finish, _pause, _play, _reverse, _setRate, _setTime, + WaitingAnimationEventName, } from "../../core/waapi"; import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"; @@ -39,7 +40,7 @@ export type AnimationHandle = { setPlaybackRate: ( rate: number | ((prevRate: number) => number) ) => AnimationHandle; - end: () => Promise>; + waitFor: (event: WaitingAnimationEventName) => Promise>; }; export const useAnimation = ( @@ -129,7 +130,8 @@ export const useAnimation = ( _setRate(getAnimation(), rate); return externalHandle; }, - end: () => _end(getAnimation()).then(() => externalHandle), + waitFor: (event: WaitingAnimationEventName) => + _waitFor(getAnimation(), event).then(() => externalHandle), } ); diff --git a/src/react/hooks/useAnimationFunction.ts b/src/react/hooks/useAnimationFunction.ts index 7515ce5..35b4b17 100644 --- a/src/react/hooks/useAnimationFunction.ts +++ b/src/react/hooks/useAnimationFunction.ts @@ -7,13 +7,14 @@ import { PlayOptions, ReverseOptions, _cancel, - _end, + _waitFor, _finish, _pause, _play, _reverse, _setRate, _setTime, + WaitingAnimationEventName, } from "../../core/waapi"; import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"; @@ -35,7 +36,9 @@ export type AnimationFunctionHandle = { setPlaybackRate: ( rate: number | ((prevRate: number) => number) ) => AnimationFunctionHandle; - end: () => Promise>; + waitFor: ( + event: WaitingAnimationEventName + ) => Promise>; }; export type ComputedTimingContext = Required< @@ -137,7 +140,8 @@ export const useAnimationFunction = ( _setRate(getAnimation(), rate); return externalHandle; }, - end: () => _end(getAnimation()).then(() => externalHandle), + waitFor: (event: WaitingAnimationEventName) => + _waitFor(getAnimation(), event).then(() => externalHandle), }; return [ externalHandle, diff --git a/src/react/hooks/useTransitionAnimation.ts b/src/react/hooks/useTransitionAnimation.ts index c4e2fd1..6c70a53 100644 --- a/src/react/hooks/useTransitionAnimation.ts +++ b/src/react/hooks/useTransitionAnimation.ts @@ -94,7 +94,7 @@ export const useTransitionAnimation = (keyframes: { animationsRef.current[currentState] ?.play() - .end() + .waitFor("finish") .then(() => { if (currentState === "exit") { notify(EXITED); diff --git a/stories/hooks/useAnimation.stories.tsx b/stories/hooks/useAnimation.stories.tsx index c195117..36f849b 100644 --- a/stories/hooks/useAnimation.stories.tsx +++ b/stories/hooks/useAnimation.stories.tsx @@ -688,9 +688,9 @@ export const Sequence: StoryObj = { const onClickAll = useCallback(async () => { try { - await animate.play({ args: "red" }).end(); - await animate.play({ args: "blue" }).end(); - await animate.play({ args: "green" }).end(); + await animate.play({ args: "red" }).waitFor("finish"); + await animate.play({ args: "blue" }).waitFor("finish"); + await animate.play({ args: "green" }).waitFor("finish"); } catch (e) { // ignore uncaught promise error } @@ -911,11 +911,11 @@ const Block = ({ i, length: n }: { i: number; length: number }) => { three.cancel(); const run = async () => { try { - await one.play().end(); + await one.play().waitFor("finish"); one.cancel(); - await two.play().end(); + await two.play().waitFor("finish"); two.cancel(); - await three.play().end(); + await three.play().waitFor("finish"); three.cancel(); run(); } catch (e) {