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

@webview-ts/react-native

v0.1.0

Published

React Native host implementation for webview-ts

Readme

@webview-ts/react-native

npm

React Native host for @webview-ts -- receives messages from the WebView, executes handlers, and sends responses and events back.

Installation

npm install @webview-ts/react-native @webview-ts/shared react-native-webview

Quick Start with Plugins

import { definePlugin, action } from '@webview-ts/shared';
import { useBridgeHost } from '@webview-ts/react-native';
import { WebView } from 'react-native-webview';

// Define plugin (shared with web side)
const camera = definePlugin('camera', {
  takePhoto: action<{ quality?: number }, { uri: string }>(),
});

function App() {
  const { webViewProps, sendEvent } = useBridgeHost({
    plugins: [
      camera.host({
        takePhoto: async (payload) => {
          // payload is typed as { quality?: number }
          const photo = await takeNativePhoto(payload.quality);
          return { uri: photo.uri };
        },
      }),
    ],
  });

  return <WebView {...webViewProps} source={{ uri: 'https://your-app.com' }} />;
}

Direct Handlers (without plugins)

For ad-hoc actions that don't need a shared plugin definition:

const { webViewProps, sendEvent } = useBridgeHost({
  handlers: {
    'device.getInfo': async () => ({
      platform: Platform.OS,
      version: String(Platform.Version),
    }),
    'storage.get': async (payload) => ({
      value: await AsyncStorage.getItem(payload.key),
    }),
  },
});

Use a generic for full type safety on direct handlers:

type MyActions = {
  'device.getInfo': { payload: void; response: { platform: string; version: string } };
  'storage.get': { payload: { key: string }; response: { value: string | null } };
};

const { webViewProps } = useBridgeHost<MyActions>({
  handlers: {
    'device.getInfo': async () => ({ platform: Platform.OS, version: '1.0' }),
    'storage.get': async (payload) => ({ value: await AsyncStorage.getItem(payload.key) }),
  },
});

Sending Events to Web

Push events from native to the web side:

const { sendEvent } = useBridgeHost({ plugins: [cameraHost] });

// Send typed event
sendEvent('location.updated', {
  latitude: 37.7749,
  longitude: -122.4194,
});

Mixing Plugins and Direct Handlers

const { webViewProps } = useBridgeHost({
  plugins: [camera.host({ takePhoto: async (p) => ({ uri: '/photo.jpg' }) })],
  handlers: {
    'custom.action': async () => ({ ok: true }),
  },
});

Duplicate action names across plugins and handlers will throw at setup time.

Host-side Middleware

The host supports the same Koa-style onion middleware as the web side:

import { createLogger } from '@webview-ts/core';

const { webViewProps } = useBridgeHost({
  plugins: [cameraHost],
  middleware: [createLogger({ level: 'debug' })],
});

Non-React Usage

Use createBridgeHost outside of React components:

import { createBridgeHost } from '@webview-ts/react-native';

const { bridgeHost, webViewProps, sendEvent } = createBridgeHost({
  plugins: [cameraHost],
  config: { debug: true, timeout: 10000 },
});

API

useBridgeHost<TActions>(options)

React hook that creates and manages a bridge host. Handlers are captured on mount.

Options:

| Option | Type | Description | | ------------ | ------------------------- | -------------------------------------------------- | | handlers | TypedHandlers<TActions> | Direct action handlers | | plugins | HostPluginResult[] | Plugin host results from plugin.host() | | middleware | Middleware[] | Koa-style middleware array | | config | BridgeHostConfig | Host configuration (debug, timeout, onError) |

Returns:

| Property | Type | Description | | -------------- | -------------------------- | ------------------------ | | webViewProps | { onMessage, ref } | Spread onto <WebView> | | sendEvent | (event, payload) => void | Push event to web side | | bridgeHost | BridgeHost | Direct access (advanced) |

createBridgeHost<TActions>(options)

Pure function equivalent of useBridgeHost. Same options, same return shape plus messageHandler.

BridgeHost

Lower-level class powering the host:

  • registerHandler(action, handler) -- register an action handler
  • unregisterHandler(action) -- remove a handler
  • sendEvent(event, payload) -- send event to web
  • handleMessage(message) -- process a BridgeMessage, returns BridgeResponse
  • use(middleware) -- add middleware
  • destroy() -- clean up

License

MIT