Native input masks for React Native — zero JS flicker, built on Nitro Modules.
Most React Native mask libraries apply the mask in JavaScript — every keystroke crosses the bridge before the field is updated, causing a visible flicker.
react-native-nitro-input-mask runs the entire mask engine natively (Swift on iOS, Kotlin on Android) via Nitro Modules, so the field is updated synchronously with no flicker.
- Zero flicker — mask applied synchronously on the native side
<NitroInputMask />— drop-in replacement for React Native's<TextInput />NitroInputMaskService— apply a mask to any string without a component- Built-in mask types —
custom,money,datetime,credit-card - Range tokens — e.g.
[1-12]for month,[1-31]for day - iOS and Android support
| Minimum | |
|---|---|
| React Native | 0.78 |
| Node | 18 |
New Architecture only. The Old Architecture is not supported.
npm install react-native-nitro-input-mask react-native-nitro-modulesyarn add react-native-nitro-input-mask react-native-nitro-modulesbun add react-native-nitro-input-mask react-native-nitro-modulescd ios && pod installDrop-in replacement for <TextInput />. Accepts all standard TextInputProps plus maskType and maskOptions.
import React, { useState } from 'react'
import type { MaskResult } from '@salve-software/react-native-nitro-input-mask'
import { NitroInputMask } from '@salve-software/react-native-nitro-input-mask'
function PhoneInput() {
const [display, setDisplay] = useState('')
const [digits, setDigits] = useState('')
function handleChange({ masked, raw }: MaskResult) {
setDisplay(masked) // '(555) 123-4567'
setDigits(raw) // '5551234567'
}
return (
<NitroInputMask
maskOptions={{ mask: '(999) 999-9999' }}
placeholder="(555) 000-0000"
keyboardType="numeric"
value={display}
onChangeText={handleChange}
/>
)
}// Money
<NitroInputMask
maskType="money"
maskOptions={{ unit: '$ ', precision: 2 }}
keyboardType="numeric"
onChangeText={({ masked, raw }) => { /* ... */ }}
/>
// Date
<NitroInputMask
maskType="datetime"
maskOptions={{ format: 'MM/DD/YYYY' }}
keyboardType="numeric"
onChangeText={({ masked, raw }) => { /* ... */ }}
/>
// Credit card
<NitroInputMask
maskType="credit-card"
maskOptions={{ issuer: 'visa-or-mastercard' }}
keyboardType="numeric"
onChangeText={({ masked, raw }) => { /* ... */ }}
/>Apply a mask to any string — useful for formatting values in lists, previews, etc.
import { NitroInputMaskService } from '@salve-software/react-native-nitro-input-mask'
const { masked, raw } = NitroInputMaskService.applyMask({
value: '5551234567',
maskOptions: { mask: '(999) 999-9999' },
})
// masked: '(555) 123-4567'
// raw: '5551234567'
const { masked: maskedMoney } = NitroInputMaskService.applyMask({
value: '123456',
maskType: 'money',
maskOptions: { unit: '$ ', precision: 2 },
})
// maskedMoney: '$ 1,234.56'
const { masked: maskedDate } = NitroInputMaskService.applyMask({
value: '06252025',
maskType: 'datetime',
maskOptions: { format: 'MM/DD/YYYY' },
})
// maskedDate: '06/25/2025'| Token | Accepts |
|---|---|
9 |
Digit (0–9) |
A |
Letter (a–z, A–Z) |
* |
Letter or digit |
[n-m] |
Integer in range n–m (e.g. [1-12], [1-31]) |
| Any other character | Literal — inserted as-is |
Extends React Native's TextInputProps.
| Prop | Type | Description |
|---|---|---|
maskType |
'custom' | 'money' | 'datetime' | 'credit-card' |
Mask type (default 'custom') |
maskOptions |
See table below | Options for the chosen mask type |
onChangeText |
(result: MaskResult) => void |
Fires on every edit with { masked, raw }. Overrides React Native's default (text: string) => void. |
| maskType | maskOptions | Docs |
|---|---|---|
'custom' (default) |
{ mask: string } |
docs/custom.md |
'money' |
{ precision?, separator?, delimiter?, unit?, suffixUnit?, zeroCents? } |
docs/money.md |
'datetime' |
{ format: string } |
docs/datetime.md |
'credit-card' |
{ issuer?, obfuscated? } |
docs/credit-card.md |
| Prop | Type | Description |
|---|---|---|
value |
string |
The raw string to mask |
maskType |
'custom' | 'money' | 'datetime' | 'credit-card' |
Mask type (default 'custom') |
maskOptions |
See table above | Options for the chosen mask type |
Returns MaskResult:
| Field | Type | Description |
|---|---|---|
masked |
string |
Formatted string as displayed to the user |
raw |
string |
Unformatted input. For money masks, this is digit-only. |
Pull requests are welcome. For major changes, please open an issue first to discuss what you'd like to change.
- Fork the repo
- Create your branch:
git checkout -b feat/your-feature - Commit your changes following Conventional Commits
- Open a pull request
MIT © Salve Software
