All files / apps/timeOff/src/screens/ChooseApproversAndObservers/hooks useSearchOverlayAnimation.ts

66.66% Statements 20/30
50% Branches 5/10
62.5% Functions 5/8
65.51% Lines 19/29

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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83                            1x     1x 1x 1x 1x   1x         1x 1x 1x 1x     1x                                           1x   1x 1x       1x 1x         1x 1x           1x              
import { useEffect, useRef, useState } from 'react';
import {
  Easing,
  runOnJS,
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';
import { InteractionManager, Keyboard, TextInput } from 'react-native';
 
type UseSearchOverlayAnimationParams = {
  isSearchOpen: boolean;
};
 
export const useSearchOverlayAnimation = ({
  isSearchOpen,
}: UseSearchOverlayAnimationParams) => {
  const searchInputRef = useRef<TextInput>(null);
  const overlayOpacity = useSharedValue(0);
  const overlayTranslateY = useSharedValue(8);
  const [isSearchInteractive, setIsSearchInteractive] = useState(false);
 
  const searchOverlayAnimatedStyle = useAnimatedStyle(() => ({
    opacity: overlayOpacity.value,
    transform: [{ translateY: overlayTranslateY.value }],
  }));
 
  useEffect(() => {
    const openDuration = 220;
    const closeDuration = 180;
    const easing = Easing.out(Easing.cubic);
    let focusTimeout: ReturnType<typeof setTimeout> | undefined;
 
    Iif (isSearchOpen) {
      setIsSearchInteractive(true);
 
      overlayOpacity.value = withTiming(1, { duration: openDuration, easing });
      overlayTranslateY.value = withTiming(0, {
        duration: openDuration,
        easing,
      });
 
      focusTimeout = setTimeout(() => {
        InteractionManager.runAfterInteractions(() => {
          searchInputRef.current?.focus();
        });
      }, 120);
 
      return () => {
        if (focusTimeout) {
          clearTimeout(focusTimeout);
        }
      };
    }
 
    Keyboard.dismiss();
 
    overlayOpacity.value = withTiming(0, { duration: closeDuration, easing });
    overlayTranslateY.value = withTiming(
      8,
      { duration: closeDuration, easing },
      finished => {
        Eif (finished) {
          runOnJS(setIsSearchInteractive)(false);
        }
      },
    );
 
    return () => {
      Iif (focusTimeout) {
        clearTimeout(focusTimeout);
      }
    };
  }, [isSearchOpen, overlayOpacity, overlayTranslateY]);
 
  return {
    searchInputRef,
    isSearchInteractive,
    shouldHideBaseContent: isSearchOpen || isSearchInteractive,
    searchOverlayAnimatedStyle,
  };
};