npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

country-data-filter

v1.3.0

Published

Geographical data for 190 countries — provinces, districts, cities and postal codes. Includes React (Ant Design / MUI) and Angular (PrimeNG) location picker cascade components with full TypeScript support.

Downloads

284

Readme

country-data-filter

A comprehensive npm package providing detailed geographical data for 190 countries — including provinces, districts, cities, postal codes, currency codes, and phone country codes. Ideal for address forms, location pickers, and any application that needs structured geographical information.

Installation

npm install country-data-filter

Data Coverage

  • 190 countries with province/state, district, and city data
  • Postal codes where available (from GeoNames dataset)
  • Currency code and international dialling code per country
  • Localized admin labels (e.g. provinceLabel: "State", districtLabel: "County")

Data Structure

Country
 └─ provinces
     └─ Province
         └─ districts
             └─ District
                 └─ cities[]
                     └─ { name, postalCode, type }

Usage

JavaScript (CommonJS)

const {
  getCountries,
  getDataByCountry,
  getDataByProvince,
  getDataByDistrict,
  getDataByCity,
  getDataByCountryProvince,
  getDataByCountryProvinceDistrict,
  getDataByCountryProvinceDistrictCity,
  getDataByEtherCountryProvinceDistrictCity,
  getDataByCountryDistrict,
  getDataByCountryCity,
  getDataByProvinceDistrict,
  getDataByProvinceCity,
  getDataByDistrictCity,
  getCurrencyByCountry,
  getDataByPostalCode,
  getCitiesWithPostalCodesByCountry,
  listFunctions,
} = require("country-data-filter");

TypeScript / ESM

import {
  getCountries,
  getDataByCountry,
  getDataByProvince,
  getDataByDistrict,
  // ... etc
} from "country-data-filter";

Functions

getCountries()

Returns an array of all supported countries with metadata.

const countries = getCountries();
// [{ name, code, currency, countryCode, provinceLabel, districtLabel }, ...]

getDataByCountry(countryCode)

Returns all provinces, districts, and cities for a country.

const result = getDataByCountry("LK");
// { provinces: [...], districts: [...], cities: [...] }

| Parameter | Type | Description | |-----------|------|-------------| | countryCode | string | ISO 3166-1 alpha-2 code (e.g. "US", "LK", "NG") |


getDataByProvince(provinceName)

Returns districts and cities for a matching province name (searches all countries).

const result = getDataByProvince("Western Province");

getDataByDistrict(districtName)

Returns the country, province, and cities for a matching district name.

const result = getDataByDistrict("Colombo");

getDataByCity(cityName)

Returns the country, province, and district for a matching city name.

const result = getDataByCity("Kandy");

getDataByCountryProvince(countryCode, provinceName)

Returns districts and cities for a specific province within a country.

const result = getDataByCountryProvince("LK", "Western Province");

getDataByCountryProvinceDistrict(countryCode, provinceName, districtName)

Returns cities for a specific district within a province and country.

const result = getDataByCountryProvinceDistrict("LK", "Western Province", "Colombo");

getDataByCountryProvinceDistrictCity(countryCode, provinceName, districtName, cityName)

Returns data for a specific city at the full hierarchy level.

const result = getDataByCountryProvinceDistrictCity("LK", "Western Province", "Colombo", "Colombo");

getDataByEtherCountryProvinceDistrictCity(countryCode?, provinceName?, districtName?, cityName?)

Flexible search — pass any combination of parameters (use null to skip a level). Returns all matching records.

// Find all districts named "Central" across all countries
const result = getDataByEtherCountryProvinceDistrictCity(null, null, "Central", null);

// Find all cities named "Springfield" in the US
const result = getDataByEtherCountryProvinceDistrictCity("US", null, null, "Springfield");

getDataByCountryDistrict(countryCode, districtName)

Returns cities for a district within a specific country.

const result = getDataByCountryDistrict("GB", "Greater London");

getDataByCountryCity(countryCode, cityName)

Returns province and district data for a city within a specific country.

const result = getDataByCountryCity("AU", "Sydney");

getDataByProvinceDistrict(provinceName, districtName)

Returns cities for a district within a named province (across all countries).

const result = getDataByProvinceDistrict("Ashanti Region", "Kumasi");

getDataByProvinceCity(provinceName, cityName)

Returns district data for a city within a named province.

const result = getDataByProvinceCity("Koshi Province", "Biratnagar");

getDataByDistrictCity(districtName, cityName)

Returns country and province data for a city within a named district.

const result = getDataByDistrictCity("Mombasa", "Mombasa");

getCurrencyByCountry(countryCode)

Returns the currency code for a country.

const currency = getCurrencyByCountry("JP");
// { currency: "JPY" }

getDataByPostalCode(postalCode)

Returns location data matching a postal code (countries with GeoNames postal data).

const result = getDataByPostalCode("10001");
// { country, province, district, city }

getCitiesWithPostalCodesByCountry(countryCode)

Returns all cities with postal codes for a given country.

const cities = getCitiesWithPostalCodesByCountry("US");

listFunctions()

Returns an object containing all available functions — useful for runtime introspection.

const fns = listFunctions();


React Location Picker

A headless, UI-library-agnostic cascade picker for country → province → district → city. You supply the dropdown component; the hook/component handles all data loading and cascade resets.

Peer dependencies

# Core (required)
npm install react react-dom

# Ant Design adapter (optional)
npm install antd

# MUI adapter (optional)
npm install @mui/material @emotion/react @emotion/styled

Quick start — Ant Design

import { AntdLocationPicker } from 'country-data-filter/react/antd';

function AddressForm() {
  return (
    <AntdLocationPicker
      onCountryChange={(code) => console.log('country code:', code)}
      onCountrySelect={(country) => console.log('full object:', country)}
      onProvinceChange={(name) => console.log('province:', name)}
      onDistrictChange={(name) => console.log('district:', name)}
      onCityChange={(name) => console.log('city name:', name)}
      onCitySelect={(city) => console.log('city + postal:', city)}
    />
  );
}

Quick start — MUI

import { MuiLocationPicker } from 'country-data-filter/react/mui';

<MuiLocationPicker
  onCountryChange={(code) => setCountry(code)}
  onProvinceChange={(name) => setProvince(name)}
  onCityChange={(name) => setCity(name)}
  onCitySelect={(city) => setPostalCode(city?.postalCode ?? '')}
/>

Quick start — any UI library (renderSelect)

import { LocationPicker } from 'country-data-filter/react';

<LocationPicker
  onCountryChange={setCountry}
  onProvinceChange={setProvince}
  renderSelect={({ id, value, options, onChange, placeholder }) => (
    <MySelect
      key={id}
      value={value}
      options={options}
      placeholder={placeholder}
      onChange={onChange}
    />
  )}
/>

Headless hook

Use useLocationPicker when you need full control over rendering:

import { useLocationPicker } from 'country-data-filter/react';

function MyPicker() {
  const {
    country, province, district, city,
    countryOptions, provinceOptions, districtOptions, cityOptions,
    setCountry, setProvince, setDistrict, setCity,
    showProvince, showDistrict, showCity,
    provinceLabel, districtLabel,
  } = useLocationPicker({
    onCountryChange: (v) => console.log(v),
    onProvinceChange: (v) => console.log(v),
    onDistrictChange: (v) => console.log(v),
    onCityChange: (v) => console.log(v),
  });

  return (
    <div>
      <select value={country ?? ''} onChange={e => setCountry(e.target.value || null)}>
        {countryOptions.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
      {showProvince && (
        <select value={province ?? ''} onChange={e => setProvince(e.target.value || null)}>
          {provinceOptions.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
        </select>
      )}
    </div>
  );
}

Controlled mode

Pass *Value props to take control of each level:

const [country, setCountry] = useState<string | null>(null);
const [city, setCity]       = useState<string | null>(null);

<LocationPicker
  countryValue={country}
  cityValue={city}
  onCountryChange={setCountry}
  onCityChange={setCity}
  renderSelect={...}
/>

Dual callbacks — value vs full object

Every level fires two callbacks: one with the form value, one with the full raw object:

| Callback | Receives | Use for | |---|---|---| | onCountryChange(value) | Mapped option value (e.g. "LK") | Form state, storing the code | | onCountrySelect(country) | Full CountryRaw object | Reading name, currency, dialling code | | onCityChange(value) | City name string | Form state | | onCitySelect(city) | Full CityRaw object | Reading postalCode, type |

<LocationPicker
  onCountryChange={(code) => form.setFieldValue('country', code)}
  onCountrySelect={(c) => setDialCode(c?.countryCode ?? '')}
  onCityChange={(name) => form.setFieldValue('city', name)}
  onCitySelect={(city) => form.setFieldValue('postalCode', city?.postalCode ?? '')}
  renderSelect={...}
/>

Custom option values

Control what value onChange receives without writing a full mapper:

// onChange receives dialling code ("+94") instead of country code ("LK")
<LocationPicker countryValueKey="countryCode" onCountryChange={setDialCode} renderSelect={...} />

// dropdown labels show currency symbols
<LocationPicker countryLabelKey="currency" onCountryChange={setCode} renderSelect={...} />

Custom mappers (advanced)

<LocationPicker
  // Combine fields in the label
  countryMapper={(c) => ({ label: `${c.name} (${c.countryCode})`, value: c.code })}
  // Show postal code next to city name
  cityMapper={(c) => ({ label: c.postalCode ? `${c.name} — ${c.postalCode}` : c.name, value: c.name })}
  renderSelect={...}
/>

Which dropdowns appear

The dropdowns shown are determined by which on*Change callbacks are provided:

| Props provided | Dropdowns shown | |---|---| | onCountryChange only | Country | | onCountryChange + onProvinceChange | Country → Province | | + onDistrictChange | Country → Province → District | | + onCityChange | Country → Province → District → City |

Props reference

| Prop | Type | Default | Description | |---|---|---|---| | onCountryChange | (value: string \| null) => void | — | Fires on country select; presence shows the country dropdown | | onCountrySelect | (country: CountryRaw \| null) => void | — | Fires with full country object on each change | | onProvinceChange | (value: string \| null) => void | — | Fires on province select; presence shows province dropdown | | onDistrictChange | (value: string \| null) => void | — | Fires on district select; presence shows district dropdown | | onCityChange | (value: string \| null) => void | — | Fires on city select; presence shows city dropdown | | onCitySelect | (city: CityRaw \| null) => void | — | Fires with full city object (includes postalCode, type) | | countryValue | string \| null | — | Controlled country value | | provinceValue | string \| null | — | Controlled province value | | districtValue | string \| null | — | Controlled district value | | cityValue | string \| null | — | Controlled city value | | countryLabelKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'name' | Field to use as option label | | countryValueKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'code' | Field to use as option value | | countryMapper | (c: CountryRaw) => LocationOption | — | Full custom mapper (overrides countryLabelKey/countryValueKey) | | provinceMapper | (name: string) => LocationOption | — | Custom province option mapper | | districtMapper | (name: string) => LocationOption | — | Custom district option mapper | | cityMapper | (city: CityRaw) => LocationOption | — | Custom city option mapper | | renderSelect | (props: RenderSelectProps) => ReactNode | required | Your dropdown renderer | | layout | 'vertical' \| 'horizontal' | 'vertical' | Flex direction of the wrapper | | className | string | — | Class added to the wrapper <div> | | style | CSSProperties | — | Inline styles for the wrapper <div> |

AntdLocationPicker additional props

| Prop | Type | Description | |---|---|---| | selectProps | Record<string, unknown> | Props spread onto every <Select> | | perLevelProps | Partial<Record<SelectLevel, Record<string, unknown>>> | Per-level prop overrides keyed by 'country' \| 'province' \| 'district' \| 'city' |

MuiLocationPicker additional props

| Prop | Type | Description | |---|---|---| | autocompleteProps | Record<string, unknown> | Props spread onto every <Autocomplete> | | textFieldProps | Record<string, unknown> | Props spread onto every <TextField> | | perLevelProps | Partial<Record<SelectLevel, { autocomplete?; textField? }>> | Per-level overrides |


Angular Location Picker

A standalone PrimeNG cascade picker for Angular 17+. Ships as raw TypeScript source — no build step required.

PrimeNG version compatibility

| PrimeNG version | Component to import | Selector | |---|---|---| | v17 – v19 | LocationPickerComponent | <cdf-location-picker> | | v20+ | LocationPickerSelectComponent | <cdf-location-picker-select> |

PrimeNG v20 removed primeng/dropdown (p-dropdown). The LocationPickerSelectComponent uses primeng/select (p-select) which is required for v18+.

Peer dependencies

npm install @angular/core @angular/common @angular/forms primeng rxjs

Setup

Add the source path to your tsconfig.json:

{
  "include": [
    "src",
    "node_modules/country-data-filter/src/angular/**/*.ts"
  ]
}

Import

Both components are exported from the main barrel. Import by name — TypeScript will resolve the correct file:

PrimeNG v17–v19:

import { LocationPickerComponent } from 'country-data-filter/angular';

PrimeNG v20+:

import { LocationPickerSelectComponent } from 'country-data-filter/angular';

Add to your component's imports array (both are standalone components):

// PrimeNG v17-v19
@Component({
  standalone: true,
  imports: [LocationPickerComponent],
  template: `<cdf-location-picker [countryControl]="countryCtrl" />`
})

// PrimeNG v20+
@Component({
  standalone: true,
  imports: [LocationPickerSelectComponent],
  template: `<cdf-location-picker-select [countryControl]="countryCtrl" />`
})

Basic usage — reactive forms

countryCtrl  = new FormControl(null);
provinceCtrl = new FormControl(null);
districtCtrl = new FormControl(null);
cityCtrl     = new FormControl(null);
<cdf-location-picker
  [countryControl]="countryCtrl"
  [provinceControl]="provinceCtrl"
  [districtControl]="districtCtrl"
  [cityControl]="cityCtrl">
</cdf-location-picker>

Event-driven (no reactive forms)

<cdf-location-picker
  (countryChange)="onCountry($event)"
  (provinceChange)="onProvince($event)"
  (cityChange)="onCity($event)">
</cdf-location-picker>
onCountry(e: CountryChangeEvent) {
  console.log(e.formValue);  // country code (or custom value key)
  console.log(e.country);    // full Country object
}

onCity(e: CityChangeEvent) {
  console.log(e.name);        // city name
  console.log(e.postalCode);  // postal code string
  console.log(e.type);        // "City" | "Town" | "Village"
}

Which dropdowns appear

Dropdowns are shown based on which controls are passed:

| Inputs provided | Dropdowns shown | |---|---| | [countryControl] only | Country | | + [provinceControl] | Country → Province | | + [districtControl] | Country → Province → District | | + [cityControl] | Country → Province → District → City |

Passing [cityControl] automatically implies all levels above it.

Custom option values

<!-- value = dialling code, e.g. "+94" for Sri Lanka -->
<cdf-location-picker countryValueKey="countryCode" [countryControl]="ctrl" />

<!-- label shows currency code -->
<cdf-location-picker countryLabelKey="currency" [countryControl]="ctrl" />

PrimeNG prop passthrough

v17–v19 — use *DropdownProps inputs:

<cdf-location-picker
  [countryControl]="countryCtrl"
  [countryDropdownProps]="{ styleClass: 'w-full', appendTo: 'body', showClear: true }"
  [provinceDropdownProps]="{ styleClass: 'w-full', filter: false }">
</cdf-location-picker>

v20+ — use *SelectProps inputs (same object shape):

<cdf-location-picker-select
  [countryControl]="countryCtrl"
  [countrySelectProps]="{ styleClass: 'w-full', appendTo: 'body', showClear: true }"
  [provinceSelectProps]="{ styleClass: 'w-full', filter: false }">
</cdf-location-picker-select>

Layout

<!-- v17-v19 -->
<cdf-location-picker layout="horizontal" [countryControl]="ctrl" />

<!-- v20+ -->
<cdf-location-picker-select layout="horizontal" [countryControl]="ctrl" />

Inputs reference

Both components share the same inputs — the only difference is *DropdownProps vs *SelectProps:

| Input | Type | Default | Description | |---|---|---|---| | countryControl | AbstractControl | — | Reactive form control for country | | provinceControl | AbstractControl | — | Reactive form control for province; presence shows province dropdown | | districtControl | AbstractControl | — | Reactive form control for district | | cityControl | AbstractControl | — | Reactive form control for city | | countryLabelKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'name' | Field to use as dropdown label | | countryValueKey | 'name' \| 'code' \| 'currency' \| 'countryCode' | 'code' | Field to use as option value | | countryDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the country <p-dropdown> | | provinceDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the province <p-dropdown> | | districtDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the district <p-dropdown> | | cityDropdownProps (v17–v19) | DropdownProps | {} | Props spread onto the city <p-dropdown> | | countrySelectProps (v20+) | SelectProps | {} | Props spread onto the country <p-select> | | provinceSelectProps (v20+) | SelectProps | {} | Props spread onto the province <p-select> | | districtSelectProps (v20+) | SelectProps | {} | Props spread onto the district <p-select> | | citySelectProps (v20+) | SelectProps | {} | Props spread onto the city <p-select> | | layout | 'vertical' \| 'horizontal' | 'vertical' | Flex direction of the wrapper |

Outputs reference

| Output | Event type | Description | |---|---|---| | (countryChange) | CountryChangeEvent | Emits { formValue, country } on country select | | (provinceChange) | NameChangeEvent | Emits { name } on province select | | (districtChange) | NameChangeEvent | Emits { name } on district select | | (cityChange) | CityChangeEvent | Emits { name, postalCode, type } on city select |

Event types

interface CountryChangeEvent {
  formValue: string | null;  // what was written to the FormControl
  country:   Country | null; // full Country object (always raw, regardless of valueKey)
}

interface NameChangeEvent {
  name: string | null;
}

interface CityChangeEvent {
  name:       string | null;
  postalCode: string;         // empty string when not available
  type?:      string;         // "City" | "Town" | "Village"
}

Supported Countries

The package covers all 190 UN-recognized sovereign states, including:

| Region | Examples | |--------|---------| | Asia | IN, CN, JP, VN, BD, PK, ID, TH, PH, KR, TR, SA, IR, IQ, MM, AF, KZ, UZ | | Africa | NG, ET, EG, CD, TZ, KE, ZA, GH, MZ, CM, CI, AO, ML, SD, MG | | Europe | DE, FR, GB, IT, ES, PL, RO, NL, BE, CZ, GR, PT, HU, AT, CH, SE | | Americas | US, BR, MX, CA, CO, AR, PE, VE, CL, EC, BO, PY, UY, CU, DO | | Oceania | AU, NZ, PG, FJ, SB, VU, WS, TO, TV, PW, NR, KI |

TypeScript Support

Full TypeScript typings are included via src/index.d.ts. Key interfaces:

interface Country {
  name: string;
  code: string;
  currency: string;
  countryCode: string;    // international dialling code, e.g. "+1"
  provinceLabel: string;  // e.g. "State", "Province", "Region"
  districtLabel: string;  // e.g. "County", "District", "Governorate"
}

interface City {
  name: string;
  postalCode: string;
  type?: "City" | "Town" | "Village";
}

interface District {
  name: string;
  cities: City[];
}

interface Province {
  name: string;
  districts: Record<string, District>;
}

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-change)
  3. Make your changes and add tests where applicable
  4. Submit a pull request with a clear description

Repository: github.com/knnadeera/country-data

License

ISC

Contact

For questions or support: [email protected]