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

react-native-transformer-text-input

v0.1.0

Published

TextInput component that allows transforming text synchronously with a worklet

Readme

TextInput component that allows transforming text synchronously with a worklet.

About

App & Flow is a Montreal-based React Native engineering and consulting studio. We partner with the world’s top companies and are recommended by Expo. Need a hand? Let’s build together. [email protected]

Demo

https://github.com/user-attachments/assets/b22041b2-f5c1-4b2a-9fd0-960d7f5b3cf9

Motivation

Transforming input as users type is common — phone numbers, credit cards, usernames. Existing approaches have trade-offs:

Pattern-based masking (e.g., react-native-advanced-input-mask) uses declarative patterns like +1 ([000]) [000]-[0000]. This works well for fixed formats, but patterns can't express conditional logic, variable-length formats, or transformations that depend on context.

Controlled inputs (value + onChangeText + state) give you full JS flexibility, but create a native → JS → re-render → native round-trip. This causes visible lag and cursor flicker—the input feels sluggish because keystrokes are corrected asynchronously.

This library combines JS flexibility with synchronous execution. Your transform runs as a worklet on the UI thread — no bridge delay, no flicker. Write any logic you need with the responsiveness of a native input.

Installation

npm install react-native-transformer-text-input

Usage

import { useRef } from 'react';
import {
  Transformer,
  TransformerTextInput,
  type TransformerTextInputInstance,
} from 'react-native-transformer-text-input';

// Transformer that formats input as a lowercase username with @ prefix
const usernameTransformer = new Transformer(({ value }) => {
  'worklet';

  const cleaned = value.replace(/[^0-9a-zA-Z]/g, '').toLowerCase();
  return { value: cleaned ? '@' + cleaned : '' };
});

function UsernameTextInput() {
  const inputRef = useRef<TransformerTextInputInstance>(null);

  const handleSubmit = () => {
    const username = inputRef.current?.getValue();
    console.log('Submitted:', username);
  };

  return (
    <TransformerTextInput
      ref={inputRef}
      transformer={usernameTransformer}
      placeholder="@username"
      autoCapitalize="none"
      autoCorrect={false}
      onSubmitEditing={handleSubmit}
    />
  );
}

API

Transformer

Create a transformer by passing a worklet function:

  • Constructor: new Transformer(worklet)
  • worklet input: an object with
    • value: current text value.
    • previousValue: previous text value (falls back to value on first call).
    • selection: current selection { start, end }.
    • previousSelection: previous selection { start, end } (falls back to selection on first call).
  • worklet return:
    • Return null or undefined to apply no transform.
    • Return an object where each field can also be null or undefined to leave that part unchanged:
      • value?: string | null to update the text.
      • selection?: { start: number; end: number } | null to update the selection.

TransformerTextInput

TransformerTextInput wraps React Native TextInput and applies a Transformer on the UI thread.

  • Props: all TextInput props (except value) plus:
    • transformer: a Transformer instance.
  • Ref: TransformerTextInputInstance with:
    • getValue(): string - Returns the current text value.
    • update(options): void - Programmatically update the input.
      • options.value: string - The new text value.
      • options.selection?: { start: number; end: number } - Optional cursor/selection position.
      • options.transform?: boolean - Whether to run the transformer on the new value (default: true).
    • clear(): void - Clear the input value.

Notes

  • The transformer must be a worklet; the Transformer constructor will throw if it isn't.
  • Prefer creating Transformer instances at module scope to avoid recreating worklets on every render.
  • This library supports the New Architecture only.

Selection Control

Selection control is needed because transforms can insert or remove characters, which would otherwise move the cursor unpredictably. The transformer can return a selection to fully control the caret/selection after a change.

Default behavior when no selection is returned:

  • If the cursor was at the end, it stays at the end.
  • If the cursor was in the middle, it moves forward by the number of inserted/removed characters.
  • If the position is ambiguous, it falls back to the end.

Built-in Transformers (Experimental)

Warning: Built-in transformers are experimental. Breaking changes may occur in minor versions.

The library includes ready-to-use transformers for common use cases.

PatternTransformer

Formats input using a pattern string with placeholder characters.

import { PatternTransformer } from 'react-native-transformer-text-input/formatters/pattern';

const dateTransformer = new PatternTransformer({
  pattern: '##/##/####',  // # = digit, A = letter, * = alphanumeric
});

// Formats as: 12/31/2024
<TransformerTextInput
  transformer={dateTransformer}
  keyboardType="number-pad"
/>

Options:

  • pattern: Pattern string where # matches digits, A matches letters, * matches alphanumeric.
  • definitions: Custom placeholder definitions (e.g., { 'X': /[0-9A-F]/i } for hex).
  • showTrailingLiterals: Show literal characters after the last input (default: false).

PhoneNumberTransformer

Formats phone numbers as the user types.

import { PhoneNumberTransformer } from 'react-native-transformer-text-input/formatters/phone-number';

const phoneTransformer = new PhoneNumberTransformer({
  country: 'US',           // Only 'US' supported currently
  debug: false,            // Enable debug logging (default: false)
});

// Formats as: +1 (555) 123-4567
<TransformerTextInput
  transformer={phoneTransformer}
  keyboardType="phone-pad"
/>

Acknowledgments

Contributing

License

MIT


Made with create-react-native-library