Skip to main content

Getting started

react-native-nitro-input is native text for React Native, built with Nitro Modules. It has three components and a number formatter:

  • NitroInput, a text input. A system text field (UITextField / EditText) owns the keyboard, editing, selection, paste and accessibility; amounts are formatted and masks applied in C++ before a frame is drawn, and the characters can reflow as they change.
  • NitroNumber, a number that animates its changes. Every digit is a wheel that rolls to its new glyph, or swaps in place the way SwiftUI's .contentTransition(.numericText()) does. NitroTime is the same wheels as a clock, timer or countdown.
  • NitroText, a single line of text that morphs to the next ("Sign in" → "Signing in…"), at about the cost of a plain label.
  • NumberFormat, Intl.NumberFormat's API formatted natively: it learns a locale's format once from the platform and formats in C++, with the same output as Hermes' Intl and none of its cost (a formatter builds in 9 µs instead of 3.3 ms on a budget Android phone).

The components are driven by C++ engines shared by iOS and Android, and share one formatting model: prefix and suffix at their own size, pinned to the top, bottom, baseline or centre of the digits; grouping and decimal separators of your choice.

Install​

  • React Native 0.78+ with the new architecture (Fabric), react-native-nitro-modules 0.37+. The iOS and Android minimums are React Native's own.
  • react-native-worklets is optional, for the input's worklet props.
bun add react-native-nitro-input react-native-nitro-modules
cd ios && pod install

With Expo, add both packages and run npx expo prebuild (or a dev client build). Both views autolink through Nitro.

Android and Nitro 0.37

Nitro never hands a Hybrid View its backgroundColor, border*, opacity, transform, testID or accessibility props on Android with React Native 0.86+, so anything you pass in style is silently dropped there while working on iOS. Fixed upstream in margelo/nitro#1655; until it ships, apply the patch from this repository with patchedDependencies (Bun) or patch-package.

A field​

Live, in your browser: the plain field. The demos on this site run the same C++ engines as the phone, compiled to WebAssembly.

import { NitroInput } from 'react-native-nitro-input'

// a form field: the system keyboard, TextInput's props and callbacks
<NitroInput placeholder="Your name" autoCapitalize="words" onSubmitEditing={({ text }) => save(text)} />

// an amount, formatted in C++ as it is typed
<NitroInput mode="number" prefix="$" fractionDigits={2} placeholder="0" onChangeValue={setAmount} />

Nothing animates unless you ask: the field draws its text the instant you type it, the way a TextInput does. NitroInput covers amounts, masks, frames and multiline.

A number​

import { NitroNumber } from 'react-native-nitro-input'

<NitroNumber value={balance} fractionDigits={2} groupingSeparator="," prefix="$" fontSize={48} fontWeight="700" />

Whenever value changes, each digit rolls from its old glyph to its new one in the direction of the change; the first value is shown without an animation. The view sizes itself to its content. NitroNumber covers the transitions, formatting and the jackpot reveal.

What runs where​

A prop change is one JSI call. From there everything runs natively: the input's formatting, masking, frame and reflow happen inside the native edit, on the main thread, before a frame is drawn; a roll runs on a CADisplayLink (Core Animation layers) or a Choreographer (Canvas). A busy JS thread delays the next value, never an animation in flight.

Both views are accessible and recyclable: VoiceOver and TalkBack read the formatted amount ($1,234.50 USD), Reduce Motion and "Remove animations" snap every animation, custom fonts resolve like Text's, and Fabric reuses the views in long lists. The benchmarks put numbers on it.