A collection of screen components, animation hooks, and navigation utilities for React Native apps using React Navigation and Reanimated.
pnpm add @mgcrea/react-native-propel-kitThis library requires the following peer dependencies:
pnpm add react-native-reanimated react-native-safe-area-context react-native-mmkv react-native-bottom-tabs @react-navigation/native @react-navigation/elements zustand superjsonA base screen wrapper that handles safe area padding and bottom tab bar insets.
import { Screen } from "@mgcrea/react-native-propel-kit";
<Screen style={{ backgroundColor: "white" }}>
<Text>Content with proper safe area handling</Text>
</Screen>A ScrollView-based screen with safe area padding, automatic content inset adjustment on iOS, and ref forwarding.
import { ScreenScrollView } from "@mgcrea/react-native-propel-kit";
<ScreenScrollView contentContainerStyle={{ padding: 16 }}>
<Text>Scrollable content</Text>
</ScreenScrollView>A FlatList-based screen with safe area padding and automatic content inset adjustment on iOS.
import { ScreenFlatList } from "@mgcrea/react-native-propel-kit";
<ScreenFlatList data={items} renderItem={({ item }) => <ItemRow item={item} />} />Drives a Reanimated shared value between 0 and 1 with configurable durations and easing.
const { animatedValue, animateIn, animateOut } = useAnimatedTransition({
duration: [150, 300],
});Interpolates a color between two values using useAnimatedTransition under the hood.
const { color, animateIn, animateOut } = useAnimatedColor({
outputRange: ["#ffffff", "#000000"],
});Manages animated color transitions for button states (background, border, text, text border) with disabled state support.
const { backgroundColor, textColor, animateIn, animateOut } = useAnimatedButton({
background: ["#3b82f6", "#2563eb"],
text: ["#ffffff", "#ffffff"],
disabled: false,
});Tracks when the navigation container is ready, returning a boolean state and a callback for the onReady prop.
const { isNavigationReady, onNavigationReady } = useNavigationReady();
<NavigationContainer onReady={onNavigationReady}>
{/* ... */}
</NavigationContainer>Executes a callback once when a condition becomes true, with an optional minimum delay since mount.
useOnceReady(isNavigationReady && !isLoading, () => {
navigationRef.dispatch(StackActions.replace("Home"));
}, { minDelay: 500 });Factory that creates a hook for persisting and restoring React Navigation state using a Zustand store backed by MMKV.
import { createNavigationStore, createNavigationPersistence } from "@mgcrea/react-native-propel-kit";
const useNavigationStore = createNavigationStore(mmkvStorage);
const useNavigationPersistence = createNavigationPersistence(useNavigationStore);
function App() {
const { isReady, initialState, onStateChange } = useNavigationPersistence();
if (!isReady) return null;
return (
<NavigationContainer initialState={initialState} onStateChange={onStateChange}>
{/* ... */}
</NavigationContainer>
);
}Computes a safe top padding value from the header height and safe area insets, with a workaround for stale header height defaults on Android.
Creates a Zustand-compatible PersistStorage adapter backed by MMKV, using SuperJSON for serialization.
import { createZustandStorage } from "@mgcrea/react-native-propel-kit";
const storage = createZustandStorage(mmkvInstance);MIT - Olivier Louvignes