Skip to content

RegionList

The headless widget behind a region picker. It produces the option rows a dropdown renders and emits a RegionListState snapshot on every change. Each change recomputes the options through one pipeline of region filter, number-type filter, search, sort, and prioritized pins. No emit fires at construction; read the bootstrap with getState.

function createRegionList<T = undefined>(options?: RegionListOptions<T>): RegionList<T>;

Before the engine is loaded it throws EngineNotReadyError; see Load the engine.

const regions = createRegionList();
regions.getState().options[0];
// { region: 'AF', callingCode: '93', displayName: 'Afghanistan', data: undefined }
Field Type Meaning
dataFactory RegionDataFactory<T> Produces the data slot from the option’s region, callingCode, and displayName; its return type flows into T.
locale string Locale for display names; 'en' by default.
sort RegionListSort 'alphabetical' (default), 'callingCode', or a comparator.
prioritize readonly RegionCode[] Regions pinned to the top, in the given order.
regionFilter readonly RegionCode[] | null Restricts the list to these regions.
numberTypeFilter readonly NumberType[] | null Keeps regions that assign at least one of these types.
searchQuery string Initial search query.
searchFn RegionSearchFn<T> Custom search predicate; the default is described under Search matching.

RegionDataFactory<T> is (input: RegionDataFactoryInput) => T, where RegionDataFactoryInput carries the option’s region, callingCode, and displayName. RegionSearchFn<T> is (query: string, option: RegionOption<T>) => boolean.

For both filters, null lifts the restriction; [] matches nothing.

type RegionOption<T = undefined> = {
readonly region: RegionCode;
readonly callingCode: string;
readonly displayName: string;
readonly data: T;
};

displayName comes from Intl.DisplayNames for the active locale, falling back to the region code. The exact string depends on the runtime’s ICU data. data carries whatever the dataFactory produced.

type RegionListState<T = undefined> = {
readonly options: readonly RegionOption<T>[];
readonly regionFilter: readonly RegionCode[] | null;
readonly numberTypeFilter: readonly NumberType[] | null;
readonly searchQuery: string;
readonly locale: string;
};

options is the list as currently rendered, with the pipeline already applied.

The default predicate runs a contains match over the display name, the region code, and the calling code, with diacritics ignored, everything lowercased, and a leading + stripped from the query.

regions.search('united');
regions
.getState()
.options.slice(0, 3)
.map((option) => option.region); // ['AE', 'GB', 'US']

Pass searchFn to replace the predicate; empty and whitespace-only queries short-circuit without calling it.

createRegionList({ sort: 'callingCode' }).getState().options[0];
// { region: 'AS', callingCode: '1', displayName: 'American Samoa', data: undefined }
createRegionList({ prioritize: ['US', 'CA'] })
.getState()
.options.slice(0, 3)
.map((option) => option.region); // ['US', 'CA', 'AF']

The built-in comparators collate display names in the list’s locale and break ties by region code. prioritize moves its regions to the top after sorting; the rest keep their order.

function regionToFlagEmoji(region: RegionCode): string;

The region’s flag emoji, built from the two Unicode regional indicator symbols for its letters. Platforms without flag emoji, notably Windows, render the two letters; for a flag on every platform, ship an SVG set keyed by the region code.

regionToFlagEmoji('US'); // '🇺🇸'
createRegionList({ dataFactory: ({ region }) => regionToFlagEmoji(region) }).getState().options[0];
// { region: 'AF', callingCode: '93', displayName: 'Afghanistan', data: '🇦🇫' }
subscribe(listener: RegionListListener<T>): () => void;

Subscribes to state changes. Returns an unsubscribe function. RegionListListener<T> is (state: RegionListState<T>) => void.

getState(): RegionListState<T>;

The current state, without subscribing.

search(query: string): void;

Updates the query and re-runs the pipeline. An unchanged query is a no-op.

localize(locale: string): void;

Switches the locale, recomputes display names and data, then re-runs the pipeline. An unchanged locale is a no-op.

refresh(): void;

Recomputes the base set and emits unconditionally. Use it when external state read by dataFactory has changed.

setRegionFilter(value: readonly RegionCode[] | null): void;

Replaces the region filter. An equal value is a no-op.

setNumberTypeFilter(value: readonly NumberType[] | null): void;

Replaces the number-type filter, matched via regionSupportsNumberTypes. An equal value is a no-op.

destroy(): void;

Clears all subscribers. Idempotent.