react-native-animated-number-flow-input
v0.1.0
Published
animated numbers with user inputs
Maintainers
Readme
react-native-animated-number-flow-input
A polished animated number input for React Native. Numbers roll through a slotmachine-style wheel animation as the user types, powered by number-flow-react-native. No theme provider required — drop it anywhere.
Features
- Animated number wheel on every keystroke (5 built-in presets)
- Hidden
TextInputcaptures the keyboard — the display is always pixel-perfect - Custom font family, size, weight
- Prefix & suffix (currency symbols, units)
- Hard value cap via
maxValue - Auto-shrinking font to prevent overflow via
autoShrink - Locale-aware number formatting (
de-DE,ja-JP, …) - Configurable decimal precision (including integers-only mode)
- Read-only display mode (no keyboard)
- Fully typed TypeScript API
Installation
npm install react-native-animated-number-flow-input
# or
yarn add react-native-animated-number-flow-inputPeer dependencies
Install these in your app if not already present:
npm install number-flow-react-native react-native-reanimated
# Reanimated 4.x also requires:
npm install react-native-worklets| Package | Required version |
| -------------------------- | --------------------------------- |
| number-flow-react-native | >=0.3.0 |
| react-native-reanimated | >=3.0.0 |
| react-native-worklets | >=0.7.0 (Reanimated 4.x only) |
Follow the Reanimated installation guide to add the Babel plugin.
Quick start
import { useState } from 'react';
import AnimatedNumberFlowInput from 'react-native-animated-number-flow-input';
export default function PriceInput() {
const [amount, setAmount] = useState('');
return (
<AnimatedNumberFlowInput
value={amount}
onChangeText={setAmount}
prefix="$"
fontSize={48}
color="#1A1A2E"
placeholderColor="#9CA3AF"
animationPreset="bouncy"
/>
);
}Props
Core
| Prop | Type | Default | Description |
| -------------- | --------------------- | ------- | ------------------------------------------------------- |
| value | string | — | Required. Controlled string value, e.g. "1234.56" |
| onChangeText | (v: string) => void | — | Fires with sanitised text on every keystroke |
| editable | boolean | true | false renders a read-only display with no keyboard |
| autoFocus | boolean | false | Focus the input on mount |
Typography
| Prop | Type | Default | Description |
| ------------ | ------------------------- | ----------- | -------------------------------------------------------- |
| fontFamily | string | system font | Any font already loaded in your app, e.g. "Inter-Bold" |
| fontSize | number | 48 | Maximum (and default) font size in points |
| fontWeight | TextStyle['fontWeight'] | — | Weight when fontFamily is omitted |
Custom font family
Pass any font already loaded in your app:
// Expo Google Fonts
<AnimatedNumberFlowInput fontFamily="Inter_700Bold" ... />
// Manual font loading
<AnimatedNumberFlowInput fontFamily="Poppins-Bold" ... />
// Platform-specific
<AnimatedNumberFlowInput
fontFamily={Platform.select({ ios: 'Georgia-Bold', android: 'serif' })}
...
/>Colors
| Prop | Type | Default | Description |
| ------------------ | -------- | ----------- | -------------------------------- |
| color | string | "#000000" | Number color |
| placeholderColor | string | "#A0A0A0" | Color shown while value is empty |
Layout
| Prop | Type | Default | Description |
| ---------------- | ----------- | ------- | -------------------------------------------------- |
| containerStyle | ViewStyle | — | Style for the outer container View |
| textStyle | TextStyle | — | Extra style merged into the NumberFlow text node |
Formatting
| Prop | Type | Default | Description |
| ------------ | ----------- | ------------- | --------------------------------------------------- |
| precision | number | 2 | Max decimal digits. Set 0 for integers only |
| locale | string | device locale | BCP 47 locale tag, e.g. "de-DE", "ja-JP" |
| prefix | string | — | Text before the number, e.g. "$". Always visible |
| suffix | string | — | Text after the number, e.g. " kg". Always visible |
| affixStyle | TextStyle | — | Style applied to both prefix and suffix |
Value constraints
| Prop | Type | Default | Description |
| ---------- | -------- | ------- | --------------------------------------------------------- |
| maxValue | number | — | Hard upper limit. Input is silently clamped to this value |
// Cap at one million
<AnimatedNumberFlowInput maxValue={1_000_000} ... />Auto-shrink
| Prop | Type | Default | Description |
| ------------- | --------- | ------- | ----------------------------------------------------------- |
| autoShrink | boolean | false | Shrink the font so the number never overflows the container |
| minFontSize | number | 16 | Minimum font size floor when autoShrink is enabled |
The container must have a finite measured width (flex parent or explicit width) for autoShrink to work. fontSize becomes the maximum; the font never exceeds it.
Works best combined with maxValue — the font stabilises at the size for the cap and stops jumping after the user reaches it:
<AnimatedNumberFlowInput
autoShrink
maxValue={9_999_999}
fontSize={52}
minFontSize={18}
containerStyle={{ width: '100%' }}
...
/>Animation
| Prop | Type | Default | Description |
| ----------------- | ----------------- | ----------- | ---------------------------------- |
| animationPreset | AnimationPreset | "default" | Number-wheel animation personality |
Presets
| Preset | Feel |
| --------- | ------------------------------------------------------ |
| default | Physical reel — fast start, long graceful deceleration |
| snappy | Tight & crisp — all transitions under 200 ms |
| bouncy | Overshoots then settles — spring-like feel |
| slow | Cinematic deceleration — twice as long as default |
| instant | No animation — updates synchronously |
<AnimatedNumberFlowInput animationPreset="bouncy" ... />Accessibility
| Prop | Type | Default | Description |
| -------------------- | -------- | ------- | ----------------------------------- |
| testID | string | — | Forwarded to the hidden TextInput |
| accessibilityLabel | string | — | Label for screen readers |
Display behaviour
| Input | Displayed |
| ------------ | --------------------------------------- |
| "" (empty) | 0.00 in placeholderColor |
| "5" | 5 |
| "5." | 5. (trailing dot rendered separately) |
| "5.3" | 5.3 |
| "5.30" | 5.30 |
| read-only | always two decimal places |
TypeScript
import type {
AnimationPreset,
AnimatedNumberFlowInputProps,
} from 'react-native-animated-number-flow-input';Source structure
src/
index.tsx — main component (orchestrator)
types.ts — exported interfaces & types
constants.ts — animation presets, format objects, defaults
utils.ts — pure helper functions
components/
HiddenInput.tsx — invisible TextInput that owns the keyboard
NumberDisplay.tsx — prefix + NumberFlow + trailing dot + suffix rowContributing
License
MIT
