All files / apps/host/src/hooks useAnimatedVisibility.ts

100% Statements 15/15
94.11% Branches 16/17
100% Functions 4/4
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52                          1x               4x   4x 4x   4x         4x 2x 2x 2x   2x 2x 2x 1x         4x              
import { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
 
import { ANIMATION_DURATION, EASING_IN_CUBIC, EASING_OUT_CUBIC } from '@/constants/animation';
 
interface VisibilityOptions {
  duration?: number;
  initialOpacity?: number;
  initialScale?: number;
  targetOpacity?: number;
  targetScale?: number;
  mode?: 'in' | 'out';
}
 
export const useAnimatedVisibility = (options: VisibilityOptions = {}) => {
  const {
    duration = ANIMATION_DURATION,
    initialOpacity = 0,
    initialScale = 0,
    targetOpacity = 1,
    targetScale = 1,
    mode = 'out',
  } = options;
 
  const opacity = useSharedValue(initialOpacity);
  const scale = useSharedValue(initialScale);
 
  const animatedStyle = useAnimatedStyle(() => ({
    opacity: opacity.value,
    transform: [{ scale: scale.value }],
  }));
 
  const setVisibility = (visible: boolean, callback?: () => void) => {
    const easing = mode === 'out' ? EASING_OUT_CUBIC : EASING_IN_CUBIC;
    const finalOpacity = visible ? targetOpacity : initialOpacity;
    const finalScale = visible ? targetScale : initialScale;
 
    opacity.value = withTiming(finalOpacity, { duration, easing });
    scale.value = withTiming(finalScale, { duration, easing }, finished => {
      if (finished && callback) {
        callback();
      }
    });
  };
 
  return {
    opacity,
    scale,
    animatedStyle,
    setVisibility,
  };
};