npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@natify/navigation-react

v1.0.2

Published

Navigation adapter for Natify Framework using `@react-navigation/native`.

Readme

@natify/navigation-react

Navigation adapter for Natify Framework using @react-navigation/native.

Installation

pnpm add @natify/navigation-react @react-navigation/native @react-navigation/native-stack react-native-screens react-native-safe-area-context

iOS

cd ios && pod install

Android

No additional configuration required.

Usage

1. Define Route Types

// types/navigation.ts
export type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Settings: undefined;
  Login: undefined;
  ProductDetail: { productId: string; name: string };
};

2. Configure the Adapter

With NatifyApp (Recommended)

// App.tsx
import { NatifyApp } from "@natify/core";
import { createReactNavigationAdapter } from "@natify/navigation-react";

// Create adapter with configuration
const navigationAdapter = createReactNavigationAdapter({
  theme: 'dark',
  screenOptions: {
    headerStyle: { backgroundColor: '#000' },
    headerTintColor: '#fff',
  },
  deeplinkConfig: {
    prefixes: ['myapp://', 'https://myapp.com'],
  },
});

export default function App() {
  return (
    <NatifyApp
      adapters={{ navigation: navigationAdapter }}
      modules={[AuthModule, ProductsModule]}
    />
  );
}

With NatifyProvider (Level 1 - Abstraction Only)

// App.tsx
import { NatifyProvider } from "@natify/core";
import { createReactNavigationAdapter } from "@natify/navigation-react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";

// Create adapter with configuration
const navigationAdapter = createReactNavigationAdapter({
  theme: 'light',
  screenOptions: {
    headerShown: true,
  },
});

const Stack = createNativeStackNavigator<RootStackParamList>();

function App() {
  return (
    <NatifyProvider adapters={{ navigation: navigationAdapter }}>
      <NavigationContainer ref={navigationAdapter.navigationRef}>
        <Stack.Navigator initialRouteName="Home">
          <Stack.Screen name="Home" component={HomeScreen} />
          <Stack.Screen name="Profile" component={ProfileScreen} />
        </Stack.Navigator>
      </NavigationContainer>
    </NatifyProvider>
  );
}

3. Usage in Components

import { useAdapter, NavigationPort } from "@natify/core";

function HomeScreen() {
  const navigation = useAdapter<NavigationPort>("navigation");

  const goToProfile = () => {
    navigation.navigate("Profile", { userId: "123" });
  };

  const goToSettings = () => {
    navigation.navigate("Settings");
  };

  return (
    <View>
      <Button title="View Profile" onPress={goToProfile} />
      <Button title="Settings" onPress={goToSettings} />
    </View>
  );
}

4. Usage Outside React (Services, Interceptors)

One of the main advantages of the adapter is being able to navigate from anywhere:

// services/auth.service.ts
import { navigationAdapter } from "../config/natify";

class AuthService {
  async logout() {
    await this.clearTokens();

    // Navigate to login from a service
    navigationAdapter.reset([{ name: "Login" }]);
  }
}

// In an HTTP interceptor
const httpAdapter = new AxiosHttpAdapter(
  "https://api.example.com",
  {},
  {
    onResponseError: async (error) => {
      if (error.response?.status === 401) {
        // Navigate to login when token expires
        navigationAdapter.reset([{ name: "Login" }]);
      }
      return Promise.reject(error);
    },
  }
);

API

NavigationPort

| Method | Return | Description | |--------|--------|-------------| | navigate(route, params?, options?) | void | Navigates to a screen | | goBack() | boolean | Goes back to previous screen | | popToTop() | void | Goes back to the beginning of the stack | | replace(route, params?) | void | Replaces current screen | | reset(routes) | void | Resets navigation stack | | getCurrentRoute() | string \| undefined | Gets current route | | getCurrentParams() | T \| undefined | Gets current parameters | | canGoBack() | boolean | Checks if can go back | | setOptions(options) | void | Configures screen options | | addListener(event, callback) | () => void | Adds event listener |

Navigation Examples

const navigation = useAdapter<NavigationPort>("navigation");

// Simple navigation
navigation.navigate("Home");

// With parameters
navigation.navigate("Profile", { userId: "123" });

// Replace (doesn't add to history)
navigation.replace("Home");

// Go back
if (navigation.canGoBack()) {
  navigation.goBack();
}

// Complete reset (useful after login/logout)
navigation.reset([
  { name: "Home" },
  { name: "Profile", params: { userId: "123" } },
]);

// Configure header dynamically
navigation.setOptions({
  title: "New Title",
  headerShown: true,
});

Listening to Events

useEffect(() => {
  const unsubscribe = navigation.addListener("focus", () => {
    console.log("Screen focused - reload data");
    fetchData();
  });

  return unsubscribe;
}, []);

Common Patterns

Authentication Flow

function useAuthNavigation() {
  const navigation = useAdapter<NavigationPort>("navigation");
  const secureStorage = useAdapter<StoragePort>("secureStorage");

  const onLoginSuccess = async (token: string) => {
    await secureStorage.setItem("auth_token", token);

    // Reset stack so user can't go back to login
    navigation.reset([{ name: "Home" }]);
  };

  const onLogout = async () => {
    await secureStorage.clear();

    // Reset to login
    navigation.reset([{ name: "Login" }]);
  };

  return { onLoginSuccess, onLogout };
}

Deep Linking

The adapter supports deeplinks automatically. Configure prefixes when creating the adapter:

// App.tsx
import { createReactNavigationAdapter } from '@natify/navigation-react';

// Create adapter with deeplinks
const navigationAdapter = createReactNavigationAdapter({
  deeplinkConfig: {
    prefixes: ['myapp://', 'https://myapp.com'],
  },
});

// In NatifyApp (passed automatically)
<NatifyApp
  adapters={{ navigation: navigationAdapter }}
  modules={[AuthModule, ProductsModule]}
/>

With theme and screenOptions:

const navigationAdapter = createReactNavigationAdapter({
  theme: 'dark', // 'light' | 'dark' | Theme object
  screenOptions: {
    headerStyle: { backgroundColor: '#000' },
    headerTintColor: '#fff',
    headerShown: true,
  },
  deeplinkConfig: {
    prefixes: ['myapp://'],
  },
});

Per-screen configuration (Recommended):

Define deeplink configuration for each screen when creating the module:

import { createModule } from "@natify/core";

export const ProductsModule = createModule("products", "Products")
  .screen({
    name: "ProductList",
    component: ProductListScreen,
    // No deeplink → automatically generated: "products/productlist"
  })
  .screen({
    name: "ProductDetail",
    component: ProductDetailScreen,
    deeplink: {
      path: "product/:productId",
      parse: {
        productId: Number, // Converts to number
      },
    },
  })
  .build();

// Resulting URLs:
// myapp://products/productlist (automatic)
// myapp://product/123 (custom) → ProductDetail with { productId: 123 }

Automatically generated URLs (without configuration):

  • myapp://auth/loginauth/Login
  • myapp://products/productlistproducts/ProductList

With custom per-screen configuration:

  • myapp://product/123products/ProductDetail with { productId: 123 }

See DEEPLINKS.md for complete deeplink documentation.

Conditional Navigation

function ProtectedRoute({ children }: { children: React.ReactNode }) {
  const navigation = useAdapter<NavigationPort>("navigation");
  const { isAuthenticated } = useAuth();

  useEffect(() => {
    if (!isAuthenticated) {
      navigation.replace("Login");
    }
  }, [isAuthenticated]);

  if (!isAuthenticated) {
    return null;
  }

  return <>{children}</>;
}

Advanced Typing

For complete parameter typing, you can use React Navigation's native hook:

import { useNavigation } from "@natify/navigation-react";
import type { NativeStackNavigationProp } from "@natify/navigation-react";
import type { RootStackParamList } from "../types/navigation";

type ProfileScreenNavigationProp = NativeStackNavigationProp<
  RootStackParamList,
  "Profile"
>;

function ProfileScreen() {
  // Complete route and parameter typing
  const navigation = useNavigation<ProfileScreenNavigationProp>();

  navigation.navigate("ProductDetail", {
    productId: "123",
    name: "Product", // TypeScript validates parameters
  });
}

Adapter Configuration

Configuration Options

interface ReactNavigationAdapterConfig {
  /**
   * Deeplink configuration (optional)
   */
  deeplinkConfig?: {
    prefixes: string[];
    config?: LinkingOptions['config'];
    filter?: (url: string) => boolean;
    getInitialURL?: () => Promise<string | null | undefined>;
    subscribe?: (listener: (url: string) => void) => () => void;
  };

  /**
   * Navigation theme ('light' | 'dark' | React Navigation Theme object)
   */
  theme?: 'light' | 'dark' | Theme;

  /**
   * Global screen options
   * Applied to all screens in the stack navigator
   */
  screenOptions?: ScreenOptions;
}

Configuration Examples

// Minimal configuration
const adapter1 = createReactNavigationAdapter();

// Theme only
const adapter2 = createReactNavigationAdapter({
  theme: 'dark',
});

// Theme and screenOptions
const adapter3 = createReactNavigationAdapter({
  theme: 'dark',
  screenOptions: {
    headerStyle: { backgroundColor: '#1a1a1a' },
    headerTintColor: '#fff',
    headerTitleStyle: { fontWeight: 'bold' },
  },
});

// Complete configuration
const adapter4 = createReactNavigationAdapter({
  theme: 'dark',
  screenOptions: {
    headerShown: true,
    animation: 'slide_from_right',
  },
  deeplinkConfig: {
    prefixes: ['myapp://', 'https://myapp.com'],
  },
});

Considerations

  1. Create adapter outside components: Must be a global instance
  2. Configuration in adapter: theme and screenOptions are configured when creating the adapter, not in NatifyApp
  3. Verify isReady: The adapter handles this internally, but keep in mind that navigation doesn't work before the container is mounted