Numora - Numeric Input Library
numora is a zero-dependency TypeScript library that turns any <input> element into a precision numeric input. Unlike <input type="number">, numora uses type="text" under the hood so you control exactly what the user can type, paste, and see.
Why numora?
If you audit the codebases of the top 10 DeFi protocols - Uniswap, Aave, Curve, Balancer - you'll notice a pattern. For the most critical UI component in finance, the numeric input, every single one has built a custom implementation from scratch.
- Uniswap maintains ~200 lines of custom regex and locale logic.
- Aave wraps a formatting library with heavy custom validation.
- Curve relies on a complex chain of hooks to handle state.
There is no standard. Every team wastes days reinventing the wheel: comma/dot separator logic, parseFloat precision loss, mobile keyboard ghost characters.
numora is the new standard for numeric inputs - a precision-first library you drop in once, configure with options, and forget about.
What you get
- Zero dependencies - no moment, no lodash, no formatting library
- 6.4 kb gzipped - negligible bundle cost
- String-only values - never converts to
Number, so no IEEE 754 rounding errors on amounts like0.1 + 0.2 - Full cursor preservation - editing in the middle of a formatted number keeps the caret in place after reformatting
- Thousand separator formatting - Standard, Indian Lakh, and East Asian Wan grouping styles
- Paste sanitization - strips non-numeric characters, expands compact notation (
1k → 1000) and scientific notation (1.5e-7 → 0.00000015) - Framework-agnostic - works with React, Vue, Svelte, Angular, or plain HTML
Vanilla JS API
The core package exports a NumoraInput class. Instantiate it with a container element and an optional FormattingOptions object. The class attaches all event listeners and manages internal state - no build step, no JSX, no reactivity system required.
import { NumoraInput } from 'numora'
const container = document.querySelector('#amount-input')
const input = new NumoraInput(container, {
maxDecimals: 2,
thousandSeparator: ',',
decimalSeparator: '.',
enableNegative: false,
})
container.addEventListener('change', (e) => {
console.log(e.target.value) // raw string, e.g. "1234.56"
})The NumoraInput class is the same engine used by the numora-react component. Both share the formatting pipeline, sanitization logic, and options interface.
Use Numora in your framework
Numora is a precision-first numeric input library that works in every modern JavaScript framework. The core NumoraInput class is vanilla TypeScript and ships with thin, idiomatic adapters for each ecosystem – no separate wrapper packages needed.
- Svelte numeric input – a 10-line
use:numoraaction for Svelte 5 and SvelteKit (SSR-safe). - Vue numeric input – a Vue 3 composable bound to a template
ref, or av-numoradirective (works with Nuxt 3, VeeValidate, FormKit, Pinia). - Angular numeric input – a standalone directive that composes with
ControlValueAccessorandFormControl<string>for Reactive Forms. - SolidJS numeric input – a tiny
onMountwrapper that writes the raw value into acreateSignal(works with SolidStart). - React numeric input – the
numora-reactpackage gives you a drop-in<NumoraInput />component with full TypeScript support and React Hook Form integration.
Next Steps
Follow the Installation guide to add numora to your project, or read Anatomy to understand the beforeinput-based architecture.