Skip to content

Commit

Permalink
feat: add onEnterFinished/onExitFinished callback
Browse files Browse the repository at this point in the history
  • Loading branch information
catalinmiron committed Nov 15, 2023
1 parent 9ff7ce9 commit 2edd978
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export function Example() {
| `exitDirection` | The direction of the animation. `1 -> top to bottom`, `-1 -> bottom to top` | NO | `number` | 0 |
| `initialEnteringDelay` | Initial enter animation delay | NO | number | 1 |
| `initialExistingDelay` | Initial exit animation delay | NO | number | -1 |
| `onEnterFinished` | callback to announce when the last item animation has finished (direction dependent) | NO | () => void | undefined |
| `onExitFinished` | callback to announce when the last item animation has finished (direction dependent) | NO | () => void | undefined |
| `enter` | [Reanimated Enter animation](https://www.reanimated3.com/docs/layout-animations/entering-exiting-animations) | NO | `() => ComplexAnimationBuilder` | `FadeInDown` |
| `exiting` | [Reanimated Exit animation](https://www.reanimated3.com/docs/layout-animations/entering-exiting-animations) | NO | `() => ComplexAnimationBuilder` | `FadeOutDown` |
| `style` | View style to be applied to Marquee container. | NO | `StyleProp<ViewStyle>` | |
Expand Down
39 changes: 34 additions & 5 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import * as React from 'react';

import type { ViewStyle } from 'react-native';
import type {
BaseAnimationBuilder,
EntryExitAnimationFunction,
Keyframe,
} from 'react-native-reanimated';
import Animated, {
ComplexAnimationBuilder,
FadeInDown,
FadeOutDown,
Layout,
runOnJS,
} from 'react-native-reanimated';
import type { ViewStyle } from 'react-native';
import type { BaseAnimationBuilder, Keyframe } from 'react-native-reanimated';
import type { EntryExitAnimationFunction } from 'react-native-reanimated';

export type StaggerProps = React.PropsWithChildren<{
stagger?: number;
Expand Down Expand Up @@ -61,6 +65,8 @@ export type StaggerProps = React.PropsWithChildren<{
| EntryExitAnimationFunction
| typeof Keyframe;

onEnterFinished?: () => void;
onExitFinished?: () => void;
initialEnteringDelay?: number;
initialExitingDelay?: number;
}>;
Expand All @@ -75,6 +81,8 @@ export function Stagger({
exiting = () => FadeOutDown.duration(400),
initialEnteringDelay = 0,
initialExitingDelay = 0,
onEnterFinished,
onExitFinished,
}: StaggerProps) {
if (!children) {
return null;
Expand All @@ -86,6 +94,14 @@ export function Stagger({
if (!React.isValidElement(child)) {
return null;
}

const isLastEnter =
index ===
(enterDirection === 1 ? React.Children.count(children) - 1 : 0);
const isLastExit =
index ===
(enterDirection === -1 ? React.Children.count(children) - 1 : 0);

return (
<Animated.View
key={child.key ?? index}
Expand All @@ -97,15 +113,28 @@ export function Stagger({
? index * stagger
: (React.Children.count(children) - index) * stagger)
)
.duration(duration)}
.duration(duration)
.withCallback((finished) => {
'worklet';
if (finished && isLastEnter && onEnterFinished) {
runOnJS(onEnterFinished)();
}
})}
exiting={(exiting() as ComplexAnimationBuilder)
.delay(
initialExitingDelay +
(exitDirection === 1
? index * stagger
: (React.Children.count(children) - index) * stagger)
)
.duration(duration)}
.duration(duration)
.withCallback((finished) => {
'worklet';
if (finished && isLastExit && onExitFinished) {
runOnJS(onExitFinished)();
}
})}
style={child.props.style}
>
{child}
</Animated.View>
Expand Down

0 comments on commit 2edd978

Please sign in to comment.