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

@ssgoi/react-native

v7.4.1

Published

Experimental SSGOI screen transitions for React Native with Expo Router integration, sharing route rules and spring physics with the web packages.

Readme

@ssgoi/react-native

Experimental SSGOI screen transitions for React Native. fade and slide share the web route matcher, physics integrators, timeline simulation, and motion geometry. Reanimated plays the numerical timelines on the UI thread.

This is the experimental first milestone in #402, published in lockstep with the web packages. A stable package version does not imply production-ready native support. Start with templates/expo from the matching release for the supported dependency baseline and device checks.

Expo Router

The example pins Expo SDK 56.0.21, Expo Router 56.2.20, React Native 0.85.3, React 19.2.3, Reanimated 4.3.1, and Worklets 0.8.3. Expo's standard navigator API is alpha; newer SDKs need separate validation. The Expo peer range is optional and broad so an unused integration does not force router upgrades.

// app/_layout.tsx
import { Ssgoi, type SsgoiConfig } from "@ssgoi/react-native";
import { SsgoiRouteBoundary } from "@ssgoi/react-native/expo-router";
import { slide } from "@ssgoi/react-native/view-transitions";

const config = {
  transitions: [{ from: "/posts", to: "/posts/*", transition: slide() }],
} satisfies SsgoiConfig;

export default function Layout() {
  return (
    <Ssgoi config={config}>
      <SsgoiRouteBoundary />
    </Ssgoi>
  );
}

Keep page files such as app/posts/index.tsx and app/posts/[id].tsx, and use Link, router.push(), router.replace(), and router.back() from Expo Router normally. The boundary discovers screens from files. It replaces the navigator in that layout; do not wrap an existing <Stack> or <Slot> inside it. Supply safe-area handling in your app.

Ssgoi provides config and selects the native platform. SsgoiRouteBoundary has the same name as @ssgoi/react/nextjs, but owns an internal Expo navigator and supplies a boundary for each screen. Popped/replaced screens keep their actual React instance and route context until completion. Routes still in the stack remain mounted and retain input and scroll state.

Configuration

  • transitions: on/except, from/to, ordered, priority, and bidirectional have the same matching semantics as the web.
  • Functional rules receive { isMobile }, based on the host width below 768 logical units.
  • middleware(from, to) rewrites matching paths without changing screen instance identity.
  • fade({ physics }) fades out then in; slide({ physics }) moves both screens together. Physics are computed in JS once and sent as numeric data to the UI runtime.
  • <Ssgoi reducedMotion="system" | "always" | "never"> defaults to the system setting. Initial preference loading also respects reduced motion.
  • onTransitionError(error) reports failed animation preparation. The latest screen is revealed and outgoing resources are released even when preparation fails.

Web TransitionConfig/WebAnimation objects cannot be passed to native config. Explicit preserveScroll restoration is rejected; mounted screens retain their native scroll state naturally. There is no automatic restoration for a removed/recreated screen yet.

Boundary options

Basic usage needs no props. initialRouteName selects the initial file-discovered screen, and style styles the native host.

resolve({ pathname, route }) returns { id, key? }, matching the naming used by the web boundary. It receives each screen's own route, including its params and instance key, rather than the currently focused global pathname. id is an absolute matching path. routeKey overrides the optional resolved key. Keys are scoped by native route instance: a constant routeKey never merges two pushed screens or keeps a popped screen alive after exit. Changing the resolved key recreates that route's boundary content; navigation animations follow changes in the active native route key.

Current scope

The first integration targets one Expo stack on iOS/Android without native headers or modal presentation. It supports push, pop, replace, direct entry, rapid-navigation cleanup, reduced motion, accessibility/touch exclusion of outgoing screens, and cleanup on host resizing or app backgrounding. Preloaded routes are rendered when they become active. A bounded watchdog settles screens that cannot finish layout or playback.

Interactive swipe, predictive-back progress, shared elements, nested-navigator coordination, explicit scroll restoration, Expo Web, and public pause/reverse/debug-host controls are follow-up work. The native header, gesture, and screen options of Expo's built-in Stack are not exposed by this boundary.

Validation

The shared runtime uses TransitionView<TTarget, TPayload>, Pose<TTarget>, Timeline<TTarget, TStyle>, and Animation<TTarget, TStyle>. Targets are opaque to core. Web imports retain HTMLElement as their default; RN binds each transition view to a stable NativeSurfaceHandle with a real native View ref. Refs stay on the RN thread while numerical plans cross to the UI runtime. Native playback uses completion callbacks rather than pretending that the web's synchronous pose getter can read current UI-thread state.

pnpm --filter @ssgoi/core build
pnpm --filter @ssgoi/react-native build
pnpm --filter @ssgoi/react-native test:run
SSGOI_TEST_PLATFORM=android pnpm --filter @ssgoi/react-native test:run
node scripts/check-native-isolation.mjs
pnpm --filter ssgoi-expo-template typecheck
pnpm --filter ssgoi-expo-template exec expo export --platform ios --platform android

The integration tests use the real Expo Router with native module mocks and a controlled frame clock. They verify React lifetime and routing behavior, not native pixels, UI-thread performance, or physical back gestures. Device/simulator checks remain necessary before treating this preview as production-ready.