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

@openeditor/native

v0.0.43

Published

React Native host for the offline OpenEditor embedded runtime.

Readme

@openeditor/native

React Native host for the offline OpenEditor embedded runtime.

The document, selection, history, and DOM NodeViews live inside one internally scrollable WebView. React Native owns the keyboard toolbar and application effects such as pickers, sheets, and navigation. The bridge sends commands and lightweight state/revision events; document JSON only crosses it when the host explicitly calls getDocument() or flushDocument().

On iOS, the host hides WKWebView's default previous/next/Done accessory bar so the OpenEditor toolbar is the only bar above the software keyboard. The SDK sticks that toolbar to the keyboard, reserves its document inset, and enables interactive keyboard dismissal while the editor scrolls. Consumers can opt back into the system bar with webViewProps={{ hideKeyboardAccessoryView: false }}.

The theme prop accepts the same OpenEditor theme-token contract used by the web React surface.

Host integration

Install the native peer dependencies:

pnpm add expo-glass-effect react-native-keyboard-controller react-native-reanimated react-native-svg react-native-webview

The package includes an Expo native module that scopes interactive iOS keyboard dismissal to the editor's own WebView. Expo autolinking discovers it; no config plugin or AppDelegate mutation is required. Rebuild the native application after adding the package or changing native dependencies. Mount the SDK provider once at the app root:

import { OpenEditorNativeProvider } from "@openeditor/native";

export default function RootLayout() {
  return <OpenEditorNativeProvider>{/* app routes */}</OpenEditorNativeProvider>;
}

The self-contained offline runtime is packaged with the component, so Metro asset customization is not required:

const editor = useRef<OpenEditorNativeController>(null);

<OpenEditorNative
  ref={editor}
  initialDocument={document}
  contentInsets={{ top: transparentHeaderHeight, bottom: 16 }}
  onDocumentChanged={({ documentRevision }) => {
    scheduleAutosave(async () => {
      const snapshot = await editor.current?.getDocument({
        minimumRevision: documentRevision,
      });
      if (snapshot) await save(snapshot.document);
    });
  }}
  nativeEffects={{
    pickAttachment: pickUploadAndReturnDurableAttachment,
    createPage: openCreatePageSheet,
    updatePage: updatePageMetadata,
    openPage: navigateToPage,
  }}
/>

The default toolbar is a keyboard-sticky, inset pill that meets the keyboard edge without a synthetic spacer. It uses native iOS glass and a theme-aware material fallback elsewhere. A custom renderToolbar returns only the toolbar content; the SDK still owns its glass surface and positioning, so do not add another KeyboardStickyView or outer background. Use toolbarContentInset when the custom toolbar needs more than the default 76-point document clearance, and toolbarOffset only when the keyboard edge itself needs a different gap.

The editor host must reach the screen's bottom edge. Do not wrap the editor in a bottom-padding SafeAreaView; the keyboard owns that edge while editing, and reserving the home-indicator inset there creates a visible toolbar gap.

The block picker derives its available page, image, and attachment commands from the supplied effect handlers. If the application cannot upload media to a durable URL, omit the corresponding picker effect rather than returning a temporary file:// URI.

Do not wrap the component in a React Native ScrollView; give it a bounded flex layout so the WebView remains the only document scroll owner. Before a screen transition or background save, call flushDocument() to commit pending composition and receive the current snapshot.

For a read-only surface, use <OpenEditorNative initialDocument={document} editable={false} showToolbar={false} />.