Skip to content

createNationalInputController

createNationalInputController builds an InputController whose value is the national notation of defaultRegion: no + and no calling code in the input. This page covers the factory and its configuration; the full method contract lives on InputController.

Every edit drives one deterministic automaton compiled from Google’s metadata, seeded with the default region’s calling code before the typed digits: parsePhoneNumber and the input controller are the same shared resolve layer, queried in batch versus per keystroke.

import { createNationalInputController } from '@telixon/core';
import type { NationalInputControllerConfig, InputController } from '@telixon/core';
export function createNationalInputController(config: NationalInputControllerConfig): InputController;
export interface NationalInputControllerConfig {
defaultRegion: RegionCode;
strict?: boolean;
initialValue?: string;
maxHistorySize?: number;
}
Field Type Default Meaning
defaultRegion RegionCode required Region whose national notation the value uses; its calling code seeds the automaton before the typed digits. Valid codes are the entries of REGION_CODES.
strict boolean false Restricts validity and the reported region to defaultRegion; see Strict mode.
initialValue string '' Starting input, resolved through the same pipeline as typed text. It becomes the first history entry, so it cannot be undone.
maxHistorySize number 150 Maximum number of retained undo entries. Non-integer sizes are floored; sizes below 1 fall back to the default.

An InputController fixed to defaultRegion. The factory resolves initialValue immediately:

const controller = createNationalInputController({ defaultRegion: 'US', initialValue: '4155550132' });
controller.currentState.value; // '(415) 555-0132'
controller.canUndo; // false

createNationalInputController throws in exactly one case: EngineNotReadyError, when it is called before the engine is initialized with ensureEngineReady.

The value is what a person writes inside defaultRegion: national digits and formatting, never a + and never the calling code. Non-digit characters in incoming text are discarded on the walk, so a pasted + is not an escape into international notation; see the pitfall under Examples.

The controller applies the region’s national prefix rules from the metadata: a typed prefix (GB 0, US 1) stays in the display value and normalizes out of E.164. When the plan expects a prefix that was not typed, the resolved number reports NATIONAL_PREFIX_MISSING:

const controller = createNationalInputController({ defaultRegion: 'GB' });
controller.setValue('7400 123456');
controller.getPhoneNumber().formatE164(); // '+447400123456'
controller.getPhoneNumber().getValidationError(); // { kind: 'NATIONAL_PREFIX_MISSING', expectedPrefix: '0' }

defaultRegion is fixed at construction; setRegion is the only way to change it, and it re-resolves the current digits under the new region:

const controller = createNationalInputController({ defaultRegion: 'US' });
controller.setValue('4155550132'); // value: '(415) 555-0132'
controller.setRegion('GB'); // value: '41555 50132', the same digits under GB rules

currentState.region reports where the digits resolve within the default calling code, so on a shared plan it can be a sibling region; with strict: true it never leaves defaultRegion:

const controller = createNationalInputController({ defaultRegion: 'US' });
controller.setValue('604 555 0199'); // a Vancouver number
controller.currentState.region; // 'CA'
const strictController = createNationalInputController({ defaultRegion: 'US', strict: true });
strictController.setValue('604 555 0199');
strictController.currentState.region; // 'US'
strictController.getPhoneNumber().isValid(); // false
import { ensureEngineReady, createNationalInputController } from '@telixon/core';
await ensureEngineReady();
const controller = createNationalInputController({ defaultRegion: 'AR' });
controller.setValue('011 15-2345-678'); // value: '011 15-2345-678', caret 15
controller.insert('011 15-2345-678', '9', 15, 15); // value: '011 15-2345-6789', caret 16
controller.getPhoneNumber().isValid(); // true
controller.deleteBackward('011 15-2345-6789', 16, 16); // value: '011 15-2345-678', caret 15
controller.undo(); // value: '011 15-2345-6789', caret 16
controller.canRedo; // true
controller.redo(); // value: '011 15-2345-678', caret 15
const phone = controller.getPhoneNumber();
phone.formatE164(); // '+549112345678'
phone.isValid(); // false
phone.getValidationError(); // { kind: 'PATTERN_MISMATCH' }

getPhoneNumber() resolves the current value, so validity moves with every edit: it was true after the insert, and after redo the shorter value is not in an accepting state. The typed 0 prefix and 15 mobile token are Argentine national notation; the metadata’s prefix rules normalize them, which is why E.164 reads +54 9 11 ....

const controller = createNationalInputController({ defaultRegion: 'GB' });
controller.setValue('+44 20 7946 0958');
controller.currentState.value; // '442079460958'

The + is discarded and the calling code digits enter the value, which is no longer the national notation of any GB number, so formatting stops. Input that carries a calling code belongs to createInternationalInputController.