+ Headless
No CSS and no image assets anywhere. You bring the markup; Telixon brings the state.
Parsing, validation, formatting, and a headless input controller. Zero dependencies.
100% geographic parity, verified against Google libphonenumberAbout 4x faster parsing, measured in CI
npm install @telixon/coreAwait ensureEngineReady() once to load the engine. Everything after that is a plain function call.
import { ensureEngineReady, parsePhoneNumber } from '@telixon/core';
await ensureEngineReady();
const number = parsePhoneNumber('+1 (415) 555-0132');
number.isValid(); // truenumber.getRegion(); // 'US'number.getNumberType(); // 'FIXED_LINE_OR_MOBILE'number.formatE164(); // '+14155550132'The conformance suite loads Google libphonenumber's own source at the exact commit the engine was compiled from, so there is no version drift between the library and its reference.
On every push to main and every pull request, CI replays the whole conformance corpus against Google's source, across every supported region, and fails the build on any divergence. Once a week, an exhaustive enumeration re-proves the result across every input the engine can distinguish, at every length. The input controllers go through the same gate: every input is typed character by character, and the controller's resolved number must equal the parser's.
Explore the results on the live dashboard.
Parity is measured over geographic regions. Non-geographic ranges (Google's region 001, for example +800) are out of scope.
Telixon compiles Google libphonenumber's metadata and rules into a deterministic finite automaton (DFA), stored as compact binary tables. Most libraries interpret those rules at runtime, on every parse. Telixon does that work once, ahead of time.
Parsing a number is a walk over the DFA, one digit per step. The state the walk ends on already holds the region, the number type, whether the number is valid, and how to format it.
The engine is lazy by design. Its tables stay out of your initial bundle until you call ensureEngineReady(), which loads and decodes them off the main thread. You choose the moment; nothing loads at import time.
One digit, one step
Measured by the benchmark suite in the repository. Full, dated runs on the live benchmarks.
A complete API for a phone-number field. It handles every action a real input has: insert, delete forward or backward, replace a selection, undo, redo. The caret and the format stay correct on every keystroke.
Hard case, Argentina mobile
In Argentina, a mobile number carries two dialing prefixes that aren't part of the number itself: a leading 0 and a mobile 15. So Telixon runs a full round-trip on every keystroke:
0 and the 15, adds the mobile 9, and gets the canonical national number.0 and the 15, then formats it.The caret survives the whole strip-and-restore round-trip.
+5491123456789Each editing method takes the current value and selection, and returns the next value and caret.
import { createNationalInputController,} from '@telixon/core';
const controller = createNationalInputController({ defaultRegion: 'AR',});
controller.insert('011 15-2345-678', '9', 15, 15);// '011 15-2345-6789', caret 16
controller.deleteBackward('011 15-2345-6789', 16, 16);// '011 15-2345-678', caret 15
controller.undo(); // '011 15-2345-6789'controller.redo(); // '011 15-2345-678'createPhoneInput binds the controller to a real <input> and handles beforeinput, paste, drop, word delete, and IME.
import { createPhoneInput,} from '@telixon/web-sdk';
const phoneInput = createPhoneInput({ mode: 'national', input: document.querySelector('input')!, defaultRegion: 'AR',});
phoneInput.subscribe(({ validationError }) => { hint.textContent = validationError?.kind ?? '';});
phoneInput.getPhoneNumber().formatE164();// '+5491123456789' for the value aboveThe full controller API lives in the docs.
What it is like to have Telixon in a codebase.
Validation failures return typed reasons with the data needed to act, never a bare boolean.
partial.getValidationError()// { kind: 'TOO_SHORT', minLength: 10 }Region and number-type unions are generated from the metadata.
controller.setRegion('USA')// compile error: not assignable to RegionCodeNo CSS and no image assets anywhere. You bring the markup; Telixon brings the state.
Importing a package does no work: no fetches, no globals, no side effects.
ESM, named exports only, sideEffects false. Bundlers drop what you don't use.
E.164, international, national, and RFC 3966, from one parsed number.
A separate sync-init entry initializes the engine where async won't do.
A searchable, locale-aware region list with a stable order, as pure state.
Flags derived arithmetically from Unicode letters, one pure function, no assets.
Each region's example number, formatted the way the field will format input.
Telixon is an ecosystem built around one core, with thin layers you add only where you need them.
Every layer is optional. Take the raw API and build exactly the behavior you need, or take a ready-made layer.