@djangocfg/ui-core 2.1.307 → 2.1.308
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
CHANGED
|
@@ -113,7 +113,7 @@ import { Button, Dialog, Table } from '@djangocfg/ui-core';
|
|
|
113
113
|
### Specialized (9)
|
|
114
114
|
`Kbd` `TokenIcon` `Item` `Portal` `ImageWithFallback` `CopyButton` `CopyField` `Flag` `LanguageFlag`
|
|
115
115
|
|
|
116
|
-
**`Flag`** / **`LanguageFlag`** — SVG country flags (3:2 aspect) backed by `country-flag-icons`. `Flag` takes an ISO 3166-1 alpha-2 `countryCode
|
|
116
|
+
**`Flag`** / **`LanguageFlag`** — SVG country flags (3:2 aspect) backed by `country-flag-icons`. `Flag` takes an ISO 3166-1 alpha-2 `countryCode` and covers every ISO country (~270 entries); `LanguageFlag` resolves a locale (`'en'`, `'pt-BR'`, `'zh_CN'`) to a country and renders the flag. Both render `null` for unknown codes. Used by `LocaleSwitcher`, `PhoneInput`, and `CountrySelect` — no emoji fallbacks anywhere.
|
|
117
117
|
|
|
118
118
|
```tsx
|
|
119
119
|
<Flag countryCode="JP" rounded className="h-3 w-4" />
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.308",
|
|
4
4
|
"description": "Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-components",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"playground": "playground dev"
|
|
92
92
|
},
|
|
93
93
|
"peerDependencies": {
|
|
94
|
-
"@djangocfg/i18n": "^2.1.
|
|
94
|
+
"@djangocfg/i18n": "^2.1.308",
|
|
95
95
|
"consola": "^3.4.2",
|
|
96
96
|
"lucide-react": "^0.545.0",
|
|
97
97
|
"moment": "^2.30.1",
|
|
@@ -160,9 +160,9 @@
|
|
|
160
160
|
"vaul": "1.1.2"
|
|
161
161
|
},
|
|
162
162
|
"devDependencies": {
|
|
163
|
-
"@djangocfg/i18n": "^2.1.
|
|
163
|
+
"@djangocfg/i18n": "^2.1.308",
|
|
164
164
|
"@djangocfg/playground": "workspace:*",
|
|
165
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
165
|
+
"@djangocfg/typescript-config": "^2.1.308",
|
|
166
166
|
"@types/node": "^24.7.2",
|
|
167
167
|
"@types/react": "^19.1.0",
|
|
168
168
|
"@types/react-dom": "^19.1.0",
|
|
@@ -13,13 +13,7 @@ import { cn } from '../../../lib';
|
|
|
13
13
|
import {
|
|
14
14
|
DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger
|
|
15
15
|
} from '../../navigation/dropdown-menu';
|
|
16
|
-
|
|
17
|
-
// Generate country flag emoji from country code
|
|
18
|
-
const getCountryFlag = (countryCode: CountryCode): string => {
|
|
19
|
-
return countryCode
|
|
20
|
-
.toUpperCase()
|
|
21
|
-
.replace(/./g, char => String.fromCodePoint(char.charCodeAt(0) + 127397))
|
|
22
|
-
}
|
|
16
|
+
import { Flag } from '../../specialized/flag';
|
|
23
17
|
|
|
24
18
|
// Get country name from country code using browser's built-in Intl.DisplayNames
|
|
25
19
|
const getCountryName = (countryCode: CountryCode): string => {
|
|
@@ -37,7 +31,6 @@ const getAllCountries = () => {
|
|
|
37
31
|
return getCountries().map(countryCode => ({
|
|
38
32
|
code: countryCode,
|
|
39
33
|
name: getCountryName(countryCode),
|
|
40
|
-
flag: getCountryFlag(countryCode),
|
|
41
34
|
dialCode: `+${getCountryCallingCode(countryCode)}`
|
|
42
35
|
})).sort((a, b) => a.name.localeCompare(b.name))
|
|
43
36
|
}
|
|
@@ -215,7 +208,7 @@ const PhoneInput = React.forwardRef<HTMLInputElement, PhoneInputProps>(
|
|
|
215
208
|
className="h-10 px-3 rounded-r-none border-r-0 flex items-center gap-2"
|
|
216
209
|
disabled={disabled}
|
|
217
210
|
>
|
|
218
|
-
<
|
|
211
|
+
<Flag countryCode={currentCountry.code} rounded className="h-3 w-4" />
|
|
219
212
|
<span className="text-sm font-mono">{currentCountry.dialCode}</span>
|
|
220
213
|
<ChevronDown className="h-3 w-3 opacity-50" />
|
|
221
214
|
</Button>
|
|
@@ -251,7 +244,7 @@ const PhoneInput = React.forwardRef<HTMLInputElement, PhoneInputProps>(
|
|
|
251
244
|
index === highlightedIndex && "bg-accent"
|
|
252
245
|
)}
|
|
253
246
|
>
|
|
254
|
-
<
|
|
247
|
+
<Flag countryCode={country.code} rounded className="h-3 w-4" />
|
|
255
248
|
<span className="flex-1 text-sm">{country.name}</span>
|
|
256
249
|
<span className="text-sm font-mono text-muted-foreground">
|
|
257
250
|
{country.dialCode}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { Check, ChevronsUpDown, Search, X } from 'lucide-react';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import { countries,
|
|
5
|
+
import { countries, type TCountryCode } from 'countries-list';
|
|
6
6
|
|
|
7
7
|
import { cn } from '../../lib/utils';
|
|
8
8
|
import { Badge } from '../data/badge';
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
import { Input } from '../forms/input';
|
|
15
15
|
import { Popover, PopoverContent, PopoverTrigger } from '../overlay/popover';
|
|
16
16
|
import { ScrollArea } from '../layout/scroll-area';
|
|
17
|
+
import { Flag } from '../specialized/flag';
|
|
17
18
|
|
|
18
19
|
export interface CountryOption {
|
|
19
20
|
code: TCountryCode;
|
|
20
21
|
name: string;
|
|
21
22
|
native: string;
|
|
22
|
-
emoji: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export type CountrySelectVariant = 'dropdown' | 'inline';
|
|
@@ -64,7 +64,7 @@ export interface CountrySelectProps {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
* Country Select component with
|
|
67
|
+
* Country Select component with SVG flags
|
|
68
68
|
*
|
|
69
69
|
* Supports:
|
|
70
70
|
* - Single and multiple selection
|
|
@@ -156,7 +156,6 @@ export function CountrySelect({
|
|
|
156
156
|
code,
|
|
157
157
|
name: getCountryName?.(code) ?? countries[code].name,
|
|
158
158
|
native: countries[code].native,
|
|
159
|
-
emoji: getEmojiFlag(code),
|
|
160
159
|
}))
|
|
161
160
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
162
161
|
}, [getCountryName, allowedCountries, excludedCountries]);
|
|
@@ -256,7 +255,7 @@ export function CountrySelect({
|
|
|
256
255
|
{isSelected && <div className="h-2 w-2 rounded-full bg-primary-foreground" />}
|
|
257
256
|
</div>
|
|
258
257
|
)}
|
|
259
|
-
<
|
|
258
|
+
<Flag countryCode={country.code} rounded className="h-4 w-6 shrink-0" />
|
|
260
259
|
<div className="flex flex-col flex-1 min-w-0">
|
|
261
260
|
<span className={cn('text-sm', isSelected && 'font-medium')}>
|
|
262
261
|
{country.name}
|
|
@@ -287,7 +286,7 @@ export function CountrySelect({
|
|
|
287
286
|
const country = selectedCountries[0]!;
|
|
288
287
|
return (
|
|
289
288
|
<div className="flex items-center gap-2">
|
|
290
|
-
<
|
|
289
|
+
<Flag countryCode={country.code} rounded className="h-3 w-4 shrink-0" />
|
|
291
290
|
<span>{country.name}</span>
|
|
292
291
|
</div>
|
|
293
292
|
);
|
|
@@ -304,7 +303,7 @@ export function CountrySelect({
|
|
|
304
303
|
variant="secondary"
|
|
305
304
|
className="mr-1 text-xs"
|
|
306
305
|
>
|
|
307
|
-
<
|
|
306
|
+
<Flag countryCode={country.code} rounded className="mr-1 h-3 w-4 shrink-0" />
|
|
308
307
|
{country.name}
|
|
309
308
|
<button
|
|
310
309
|
className="ml-1 rounded-full hover:bg-muted-foreground/20"
|
|
@@ -379,7 +378,7 @@ export function CountrySelect({
|
|
|
379
378
|
isSelected ? "opacity-100" : "opacity-0"
|
|
380
379
|
)}
|
|
381
380
|
/>
|
|
382
|
-
<
|
|
381
|
+
<Flag countryCode={country.code} rounded className="mr-2 h-4 w-6 shrink-0" />
|
|
383
382
|
<div className="flex flex-col flex-1 min-w-0">
|
|
384
383
|
<span className="truncate">{country.name}</span>
|
|
385
384
|
{showNativeName && country.native !== country.name && (
|
|
@@ -402,4 +401,3 @@ export function CountrySelect({
|
|
|
402
401
|
|
|
403
402
|
// Re-export types for convenience
|
|
404
403
|
export type { TCountryCode } from 'countries-list';
|
|
405
|
-
export { getEmojiFlag } from 'countries-list';
|
|
@@ -1,38 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Static map: ISO 3166-1 alpha-2 country code → SVG React component.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Re-exports every flag from `country-flag-icons` (~270 entries) so the
|
|
5
|
+
* `Flag` component covers every consumer — locale switchers, phone-input
|
|
6
|
+
* country picker, country select, etc. Tree-shaking keeps unused flags out
|
|
7
|
+
* of the final bundle when consumers reach for `<Flag countryCode>`
|
|
8
|
+
* directly with a constant code.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import type * as React from 'react';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
AF, AL, AM, AZ,
|
|
14
|
-
BA, BD, BE, BG, BI, BO, BR, BT, BW, BY,
|
|
15
|
-
CA, CD, CF, CH, CN, CZ,
|
|
16
|
-
DE, DK,
|
|
17
|
-
EE, ER, ES, ET,
|
|
18
|
-
FI, FJ, FO, FR,
|
|
19
|
-
GB, GE, GH, GL, GR, GU,
|
|
20
|
-
HR, HT, HU,
|
|
21
|
-
ID, IE, IL, IM, IN, IQ, IR, IS, IT,
|
|
22
|
-
JP,
|
|
23
|
-
KE, KG, KH, KR, KZ,
|
|
24
|
-
LA, LK, LT, LU, LV,
|
|
25
|
-
MD, MG, MH, MK, ML, MM, MN, MT, MV, MW, MY,
|
|
26
|
-
NA, NE, NG, NL, NO, NP, NR, NZ,
|
|
27
|
-
PE, PF, PG, PH, PK, PL, PY,
|
|
28
|
-
RO, RS, RU, RW,
|
|
29
|
-
SA, SE, SI, SK, SN, SO, SZ,
|
|
30
|
-
TH, TJ, TM, TO, TR,
|
|
31
|
-
UA, UG, US, UZ,
|
|
32
|
-
VA, VN, VU,
|
|
33
|
-
WS,
|
|
34
|
-
ZA, ZW,
|
|
35
|
-
} from 'country-flag-icons/react/3x2';
|
|
12
|
+
import * as Flags from 'country-flag-icons/react/3x2';
|
|
36
13
|
|
|
37
14
|
/**
|
|
38
15
|
* `country-flag-icons` types its components against `HTMLSVGElement`
|
|
@@ -42,27 +19,4 @@ import {
|
|
|
42
19
|
*/
|
|
43
20
|
export type FlagSvgComponent = (props: React.SVGProps<SVGSVGElement> & React.HTMLAttributes<SVGSVGElement>) => React.JSX.Element;
|
|
44
21
|
|
|
45
|
-
export const FLAG_COMPONENTS =
|
|
46
|
-
AF, AL, AM, AZ,
|
|
47
|
-
BA, BD, BE, BG, BI, BO, BR, BT, BW, BY,
|
|
48
|
-
CA, CD, CF, CH, CN, CZ,
|
|
49
|
-
DE, DK,
|
|
50
|
-
EE, ER, ES, ET,
|
|
51
|
-
FI, FJ, FO, FR,
|
|
52
|
-
GB, GE, GH, GL, GR, GU,
|
|
53
|
-
HR, HT, HU,
|
|
54
|
-
ID, IE, IL, IM, IN, IQ, IR, IS, IT,
|
|
55
|
-
JP,
|
|
56
|
-
KE, KG, KH, KR, KZ,
|
|
57
|
-
LA, LK, LT, LU, LV,
|
|
58
|
-
MD, MG, MH, MK, ML, MM, MN, MT, MV, MW, MY,
|
|
59
|
-
NA, NE, NG, NL, NO, NP, NR, NZ,
|
|
60
|
-
PE, PF, PG, PH, PK, PL, PY,
|
|
61
|
-
RO, RS, RU, RW,
|
|
62
|
-
SA, SE, SI, SK, SN, SO, SZ,
|
|
63
|
-
TH, TJ, TM, TO, TR,
|
|
64
|
-
UA, UG, US, UZ,
|
|
65
|
-
VA, VN, VU,
|
|
66
|
-
WS,
|
|
67
|
-
ZA, ZW,
|
|
68
|
-
} as unknown as Record<string, FlagSvgComponent>;
|
|
22
|
+
export const FLAG_COMPONENTS = Flags as unknown as Record<string, FlagSvgComponent>;
|