localized-regions 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amit Tank
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # localized-regions
2
+
3
+ [![npm version](https://img.shields.io/npm/v/localized-regions.svg)](https://www.npmjs.com/package/localized-regions)
4
+ [![npm downloads](https://img.shields.io/npm/dm/localized-regions.svg)](https://www.npmjs.com/package/localized-regions)
5
+ [![license](https://img.shields.io/npm/l/localized-regions.svg)](./LICENSE)
6
+ [![types](https://img.shields.io/npm/types/localized-regions.svg)](./dist/index.d.ts)
7
+
8
+ **Country, province and city data with bilingual localized labels and ISO 3166 codes.**
9
+ Get country / province / city dropdown options with labels like `Spain (España)`, stable ISO
10
+ 3166-1 and ISO 3166-2 codes, and the full set of **50 Spanish provinces** (not the 17
11
+ autonomous communities). Framework-agnostic and TypeScript-first: the data drops straight into
12
+ **react-select**, **MUI Autocomplete**, or any dropdown.
13
+
14
+ ```ts
15
+ import { countryOptions, provinceOptions } from 'localized-regions';
16
+
17
+ countryOptions('es'); // [{ value: 'ES', label: 'Spain (España)' }, { value: 'NL', label: 'Netherlands (Países Bajos)' }, ...]
18
+ provinceOptions('ES'); // [{ value: 'ES-MA', label: 'Málaga' }, { value: 'ES-B', label: 'Barcelona' }, ...]
19
+ ```
20
+
21
+ ## Features
22
+
23
+ - **Bilingual / localized country labels** - `Spain (España)`, `Germany (Alemania)`, `France (Francia)`, computed from the browser-native `Intl.DisplayNames` for any locale.
24
+ - **Correct Spanish provinces** - all **50 provinces** with ISO 3166-2 codes and their parent autonomous community. (Popular datasets like `country-state-city` return only ~16 of them for Spain.)
25
+ - **Stable, invoicing-safe values** - country = ISO 3166-1 code (`ES`), province = ISO 3166-2 code (`ES-MA`). Labels are display-only.
26
+ - **Full city database** - cities for every country, sourced from `country-state-city` at runtime.
27
+ - **Framework-agnostic** - no React / MUI / Chakra dependency. Plain data plus ready-to-use `{ value, label }` options.
28
+ - **TypeScript types included.**
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ npm install localized-regions
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ```ts
39
+ import {
40
+ getCountries, getProvinces, getCities,
41
+ countryOptions, provinceOptions, cityOptions,
42
+ formatCountryLabel,
43
+ } from 'localized-regions';
44
+
45
+ // Bilingual country labels (the locale drives the native part)
46
+ getCountries({ locale: 'es' }); // [{ code:'ES', name:'Spain', localized:'España', label:'Spain (España)' }, ...]
47
+ getCountries(); // English-only labels
48
+
49
+ // Spain -> 50 provinces (ISO 3166-2 codes + community grouping)
50
+ getProvinces('ES'); // [{ code:'ES-MA', countryCode:'ES', name:'Málaga', community:'Andalusia', communityCode:'ES-AN' }, ...]
51
+
52
+ // Cities (full database)
53
+ getCities('ES', 'ES-MA');
54
+
55
+ // Ready-to-use dropdown options
56
+ countryOptions('es'); // [{ value:'ES', label:'Spain (España)' }, ...]
57
+ provinceOptions('ES'); // [{ value:'ES-MA', label:'Málaga' }, ...]
58
+ cityOptions('ES', 'ES-MA'); // [{ value:'Málaga', label:'Málaga' }, ...]
59
+
60
+ formatCountryLabel('ES', 'es'); // "Spain (España)"
61
+ ```
62
+
63
+ ### With react-select (editable / creatable dropdowns)
64
+
65
+ ```tsx
66
+ import CreatableSelect from 'react-select/creatable';
67
+ import { provinceOptions } from 'localized-regions';
68
+
69
+ <CreatableSelect
70
+ options={provinceOptions('ES')} // 50 Spanish provinces
71
+ onChange={(opt) => save(opt?.value)} // store the ISO 3166-2 code, e.g. "ES-MA"
72
+ onCreateOption={(typed) => saveCustom(typed)} // allow a manual free-text correction
73
+ />
74
+ ```
75
+
76
+ ### With MUI Autocomplete
77
+
78
+ ```tsx
79
+ import Autocomplete from '@mui/material/Autocomplete';
80
+ import { countryOptions } from 'localized-regions';
81
+
82
+ <Autocomplete options={countryOptions('es')} getOptionLabel={(o) => o.label} />
83
+ ```
84
+
85
+ ## API
86
+
87
+ | Function | Returns |
88
+ | --- | --- |
89
+ | `getCountries({ locale? })` | `CountryOption[]` - all countries, bilingual when a locale is given |
90
+ | `getCountry(code)` | `Country` |
91
+ | `formatCountryLabel(code, locale?)` | bilingual / English label string |
92
+ | `getProvinces(countryCode)` | `Province[]` (Spain = curated 50) |
93
+ | `getProvince(provinceCode)` | `Province` |
94
+ | `getCities(countryCode, provinceCode?)` | `City[]` |
95
+ | `countryOptions(locale?)` | `Option[]` (`{ value, label }`) |
96
+ | `provinceOptions(countryCode)` | `Option[]` |
97
+ | `cityOptions(countryCode, provinceCode?)` | `Option[]` |
98
+
99
+ ## How the data is built
100
+
101
+ Data is generated at build time (`npm run generate`) and committed under `data/`:
102
+
103
+ - **Countries** - `Intl.DisplayNames` (English) plus a code list, 250 countries.
104
+ - **Provinces** - `iso-3166-2` subdivisions. Spain is curated to 50 provinces, with 4 regional-language names aliased to their common form (Nafarroa -> Navarra, Balears -> Balearic Islands, Alacant -> Alicante, Castelló -> Castellón).
105
+ - **Cities** - `country-state-city` at runtime.
106
+
107
+ Regenerate after a data-source bump:
108
+
109
+ ```bash
110
+ npm run generate && npm run build
111
+ ```
112
+
113
+ ## Notes and limitations
114
+
115
+ - **Spain city cascade is community-level.** The source city data groups Spanish cities under autonomous communities, not the 50 provinces, so `getCities('ES', 'ES-MA')` returns the parent community's cities (best-effort). City is best treated as a free-text field.
116
+ - **Bilingual labels are country-level only.** `Intl.DisplayNames` does not localize subdivisions; province names are shown as-is.
117
+
118
+ ## License
119
+
120
+ MIT (c) Amit Tank. See [LICENSE](./LICENSE).