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.NitroTimeis 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'Intland 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-modules0.37+. The iOS and Android minimums are React Native's own. react-native-workletsis 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.
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.