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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 1x 12x 12x 12x 12x 12x 12x 9x 9x 9x 9x 6x 6x 6x 6x 1x 1x 6x 6x 6x 3x 3x 3x 3x 2x 3x 3x 12x 1x 7x 7x 5x 5x 5x 1x 5x 5x 5x 5x 7x | import { useEffect, useRef, useState } from "react";
import {
Easing,
runOnJS,
useAnimatedStyle,
useSharedValue,
withTiming,
} from "react-native-reanimated";
import { InteractionManager, Keyboard, Platform, 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;
if (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 () => {
Eif (focusTimeout) {
clearTimeout(focusTimeout);
}
};
}
Keyboard.dismiss();
overlayOpacity.value = withTiming(0, { duration: closeDuration, easing });
overlayTranslateY.value = withTiming(
8,
{ duration: closeDuration, easing },
(finished: boolean | undefined) => {
if (finished) {
runOnJS(setIsSearchInteractive)(false);
}
},
);
return () => {
Iif (focusTimeout) {
clearTimeout(focusTimeout);
}
};
}, [isSearchOpen, overlayOpacity, overlayTranslateY]);
return {
searchInputRef,
isSearchInteractive,
shouldHideBaseContent: isSearchOpen || isSearchInteractive,
searchOverlayAnimatedStyle,
};
};
export const useKeyboardPadding = (): number => {
const [keyboardPadding, setKeyboardPadding] = useState(0);
useEffect(() => {
const showEvent = Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow";
const hideEvent = Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide";
const show = Keyboard.addListener(showEvent, (e) =>
setKeyboardPadding(e.endCoordinates.height),
);
const hide = Keyboard.addListener(hideEvent, () => setKeyboardPadding(0));
return () => {
show.remove();
hide.remove();
};
}, []);
return keyboardPadding;
};
|