@tw-labs/countries 0.0.1
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/README.md +333 -0
- package/dist/chunk-T2ZQU6E6.mjs +530 -0
- package/dist/chunk-T2ZQU6E6.mjs.map +1 -0
- package/dist/data.d.cts +253 -0
- package/dist/data.d.ts +253 -0
- package/dist/data.js +504 -0
- package/dist/data.js.map +1 -0
- package/dist/data.mjs +3 -0
- package/dist/data.mjs.map +1 -0
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +579 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +45 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.cts +37 -0
- package/dist/react.d.ts +37 -0
- package/dist/react.js +581 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +579 -0
- package/dist/react.mjs.map +1 -0
- package/dist/types-Dte-oYZc.d.cts +32 -0
- package/dist/types-Dte-oYZc.d.ts +32 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# @tw-labs/countries
|
|
4
|
+
|
|
5
|
+
**Comprehensive country data with utilities and an optional React hook.**
|
|
6
|
+
|
|
7
|
+
TypeScript-first · Framework-agnostic · Tree-shakeable · Zero dependencies
|
|
8
|
+
|
|
9
|
+
<br />
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/@tw-labs/countries)
|
|
12
|
+
[](https://opensource.org/licenses/MIT)
|
|
13
|
+
[](https://www.typescriptlang.org)
|
|
14
|
+
[](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking)
|
|
15
|
+
[](https://nextjs.org)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **195+ countries** — ISO alpha-2/alpha-3 codes, name, phone dial code, capital, continent, currency, and timezones
|
|
24
|
+
- **Flag support** — emoji flags, PNG (20px, 40px), and SVG via [flagcdn.com](https://flagcdn.com)
|
|
25
|
+
- **Tree-shakeable** — import only the countries you need via the `/data` subpath
|
|
26
|
+
- **Framework-agnostic core** — works in Node.js, Vue, Svelte, and anywhere else
|
|
27
|
+
- **React hook** — `useCountries` with filtering, sorting, and conditional flag types
|
|
28
|
+
- **Next.js ready** — `"use client"` built into the React entry, core works in Server Components
|
|
29
|
+
- **TypeScript-first** — full type safety and IntelliSense out of the box
|
|
30
|
+
- **Zero dependencies** — no runtime dependencies
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
<table>
|
|
37
|
+
<tr>
|
|
38
|
+
<td>
|
|
39
|
+
<img src="https://img.shields.io/badge/npm-CB3837?style=flat-square&logo=npm&logoColor=white" alt="npm" />
|
|
40
|
+
</td>
|
|
41
|
+
<td>
|
|
42
|
+
<code>npm install @tw-labs/countries</code>
|
|
43
|
+
</td>
|
|
44
|
+
</tr>
|
|
45
|
+
<tr>
|
|
46
|
+
<td>
|
|
47
|
+
<img src="https://img.shields.io/badge/yarn-2C8EBB?style=flat-square&logo=yarn&logoColor=white" alt="yarn" />
|
|
48
|
+
</td>
|
|
49
|
+
<td>
|
|
50
|
+
<code>yarn add @tw-labs/countries</code>
|
|
51
|
+
</td>
|
|
52
|
+
</tr>
|
|
53
|
+
<tr>
|
|
54
|
+
<td>
|
|
55
|
+
<img src="https://img.shields.io/badge/pnpm-F69220?style=flat-square&logo=pnpm&logoColor=white" alt="pnpm" />
|
|
56
|
+
</td>
|
|
57
|
+
<td>
|
|
58
|
+
<code>pnpm add @tw-labs/countries</code>
|
|
59
|
+
</td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td>
|
|
63
|
+
<img src="https://img.shields.io/badge/bun-000000?style=flat-square&logo=bun&logoColor=white" alt="bun" />
|
|
64
|
+
</td>
|
|
65
|
+
<td>
|
|
66
|
+
<code>bun add @tw-labs/countries</code>
|
|
67
|
+
</td>
|
|
68
|
+
</tr>
|
|
69
|
+
</table>
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Import Paths
|
|
74
|
+
|
|
75
|
+
| Path | Use case |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `@tw-labs/countries` | Framework-agnostic utilities (Node, Vue, Svelte, Next.js server) |
|
|
78
|
+
| `@tw-labs/countries/react` | React hook (`useCountries`) |
|
|
79
|
+
| `@tw-labs/countries/data` | Named country exports — fully tree-shakeable |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Core Utilities
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import {
|
|
87
|
+
getAllCountries,
|
|
88
|
+
getAllCountriesWithFlags,
|
|
89
|
+
getCountryByCode,
|
|
90
|
+
getCountryByAlpha3,
|
|
91
|
+
getCountryByPhone,
|
|
92
|
+
withFlags,
|
|
93
|
+
} from "@tw-labs/countries";
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `getCountryByCode(code)`
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const country = getCountryByCode("US");
|
|
100
|
+
// {
|
|
101
|
+
// code: "US",
|
|
102
|
+
// alpha3: "USA",
|
|
103
|
+
// label: "United States",
|
|
104
|
+
// phone: "1",
|
|
105
|
+
// capital: "Washington, D.C.",
|
|
106
|
+
// continent: "North America",
|
|
107
|
+
// currency: { code: "USD", symbol: "$", name: "United States Dollar" },
|
|
108
|
+
// timezones: ["America/New_York", "America/Chicago", ...]
|
|
109
|
+
// }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `getCountryByAlpha3(alpha3)`
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const country = getCountryByAlpha3("GBR");
|
|
116
|
+
// { code: "GB", alpha3: "GBR", label: "United Kingdom", ... }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `getCountryByPhone(phone)`
|
|
120
|
+
|
|
121
|
+
Returns an array since multiple countries can share a dial code.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const countries = getCountryByPhone("1");
|
|
125
|
+
// [{ code: "US", ... }, { code: "CA", ... }, { code: "PR", ... }, ...]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `getAllCountries(options?)`
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// All countries
|
|
132
|
+
const all = getAllCountries();
|
|
133
|
+
|
|
134
|
+
// Filtered
|
|
135
|
+
const european = getAllCountries({
|
|
136
|
+
filter: (c) => c.continent === "Europe",
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Sorted
|
|
140
|
+
const sorted = getAllCountries({
|
|
141
|
+
sort: { by: "label", order: "asc" },
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Filtered + sorted
|
|
145
|
+
const result = getAllCountries({
|
|
146
|
+
filter: (c) => c.continent === "Asia",
|
|
147
|
+
sort: { by: "label", order: "asc" },
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `getAllCountriesWithFlags(options?)`
|
|
152
|
+
|
|
153
|
+
Same as `getAllCountries` but each country includes flag data.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const countries = getAllCountriesWithFlags();
|
|
157
|
+
// Each country has: flagEmoji, flagPng20, flagPng40, flagSvg, srcSet
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `withFlags(country)`
|
|
161
|
+
|
|
162
|
+
Add flag data to a single country object.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const country = getCountryByCode("JP");
|
|
166
|
+
const withFlagData = withFlags(country!);
|
|
167
|
+
// { ...country, flagEmoji: "🇯🇵", flagPng20: "...", flagSvg: "...", ... }
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Tree-Shakeable Data Imports
|
|
173
|
+
|
|
174
|
+
For the best bundle size when you know your countries at build time:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { US, GB, DE, FR } from "@tw-labs/countries/data";
|
|
178
|
+
// Only these 4 country objects are included in your bundle
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
> **Note:** `getCountryByCode("US")` is for runtime dynamic lookups and includes the full dataset. Use the `/data` subpath when the country codes are known at build time.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## React Hook
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { useCountries } from "@tw-labs/countries/react";
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The `@tw-labs/countries/react` entry has `"use client"` built in — no need to add it yourself in Next.js.
|
|
192
|
+
|
|
193
|
+
### Basic usage
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
function CountryList() {
|
|
197
|
+
const countries = useCountries({});
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<ul>
|
|
201
|
+
{countries.map((c) => (
|
|
202
|
+
<li key={c.code}>
|
|
203
|
+
{c.label} (+{c.phone})
|
|
204
|
+
</li>
|
|
205
|
+
))}
|
|
206
|
+
</ul>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### With flags
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
function FlagList() {
|
|
215
|
+
const countries = useCountries({ includeFlags: true });
|
|
216
|
+
// TypeScript knows each country has flagEmoji, flagPng20, etc.
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div>
|
|
220
|
+
{countries.map((c) => (
|
|
221
|
+
<div key={c.code}>
|
|
222
|
+
<span>{c.flagEmoji}</span>
|
|
223
|
+
<img src={c.flagPng40} alt={`${c.label} flag`} />
|
|
224
|
+
<span>{c.label}</span>
|
|
225
|
+
</div>
|
|
226
|
+
))}
|
|
227
|
+
</div>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### With filtering and sorting
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
function SearchableCountryPicker() {
|
|
236
|
+
const [query, setQuery] = useState("");
|
|
237
|
+
|
|
238
|
+
const countries = useCountries({
|
|
239
|
+
includeFlags: true,
|
|
240
|
+
filter: query
|
|
241
|
+
? (c) =>
|
|
242
|
+
c.label.toLowerCase().includes(query.toLowerCase()) ||
|
|
243
|
+
c.code.toLowerCase().includes(query.toLowerCase()) ||
|
|
244
|
+
c.phone.includes(query)
|
|
245
|
+
: undefined,
|
|
246
|
+
sort: { by: "label", order: "asc" },
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<div>
|
|
251
|
+
<input
|
|
252
|
+
placeholder="Search countries..."
|
|
253
|
+
value={query}
|
|
254
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
255
|
+
/>
|
|
256
|
+
<p>{countries.length} results</p>
|
|
257
|
+
{countries.map((c) => (
|
|
258
|
+
<div key={c.code}>
|
|
259
|
+
{c.flagEmoji} {c.label} (+{c.phone})
|
|
260
|
+
</div>
|
|
261
|
+
))}
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Sort options
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
useCountries({ sort: { by: "label", order: "asc" } }); // A → Z by name
|
|
271
|
+
useCountries({ sort: { by: "code", order: "asc" } }); // AD → ZW
|
|
272
|
+
useCountries({ sort: { by: "phone", order: "asc" } }); // by dial code
|
|
273
|
+
useCountries({ sort: { by: "continent", order: "asc" } }); // grouped by continent
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Next.js Usage
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
// app/components/PhoneInput.tsx — Client Component
|
|
282
|
+
// No need to add "use client" manually — it's built into @tw-labs/countries/react
|
|
283
|
+
import { useCountries } from "@tw-labs/countries/react";
|
|
284
|
+
|
|
285
|
+
// app/api/validate/route.ts — Server Component / Route Handler
|
|
286
|
+
// Works with no configuration — no "use client" in the core entry
|
|
287
|
+
import { getCountryByCode } from "@tw-labs/countries";
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## TypeScript Types
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import type {
|
|
296
|
+
Country,
|
|
297
|
+
CountryWithFlags,
|
|
298
|
+
Currency,
|
|
299
|
+
FilterSortOptions,
|
|
300
|
+
SortBy,
|
|
301
|
+
} from "@tw-labs/countries";
|
|
302
|
+
|
|
303
|
+
type Currency = {
|
|
304
|
+
code: string; // "USD"
|
|
305
|
+
symbol: string; // "$"
|
|
306
|
+
name: string; // "United States Dollar"
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
type Country = {
|
|
310
|
+
code: string; // ISO alpha-2 "US"
|
|
311
|
+
alpha3: string; // ISO alpha-3 "USA"
|
|
312
|
+
label: string; // "United States"
|
|
313
|
+
phone: string; // "1"
|
|
314
|
+
capital: string; // "Washington, D.C."
|
|
315
|
+
continent: string; // "North America"
|
|
316
|
+
currency: Currency;
|
|
317
|
+
timezones: string[]; // ["America/New_York", ...]
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
type CountryWithFlags = Country & {
|
|
321
|
+
flagEmoji: string; // "🇺🇸"
|
|
322
|
+
flagPng20: string; // https://flagcdn.com/w20/us.png
|
|
323
|
+
flagPng40: string; // https://flagcdn.com/w40/us.png
|
|
324
|
+
flagSvg: string; // https://flagcdn.com/us.svg
|
|
325
|
+
srcSet: string; // https://flagcdn.com/w40/us.png 2x
|
|
326
|
+
};
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## License
|
|
332
|
+
|
|
333
|
+
MIT © [TechWebster](https://techwebster.com)
|