@djangocfg/ui-core 2.1.162 → 2.1.164
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.164",
|
|
4
4
|
"description": "Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-components",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"playground": "playground dev"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
|
-
"@djangocfg/i18n": "^2.1.
|
|
79
|
+
"@djangocfg/i18n": "^2.1.164",
|
|
80
80
|
"react-device-detect": "^2.2.3",
|
|
81
81
|
"consola": "^3.4.2",
|
|
82
82
|
"lucide-react": "^0.545.0",
|
|
@@ -138,9 +138,9 @@
|
|
|
138
138
|
"vaul": "1.1.2"
|
|
139
139
|
},
|
|
140
140
|
"devDependencies": {
|
|
141
|
-
"@djangocfg/i18n": "^2.1.
|
|
141
|
+
"@djangocfg/i18n": "^2.1.164",
|
|
142
142
|
"@djangocfg/playground": "workspace:*",
|
|
143
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
143
|
+
"@djangocfg/typescript-config": "^2.1.164",
|
|
144
144
|
"@types/node": "^24.7.2",
|
|
145
145
|
"@types/react": "^19.1.0",
|
|
146
146
|
"@types/react-dom": "^19.1.0",
|
package/src/components/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ export { MultiSelectPro } from './multi-select-pro';
|
|
|
23
23
|
export type { MultiSelectProOption, MultiSelectProGroup, MultiSelectProProps, MultiSelectProRef, AnimationConfig, ResponsiveConfig } from './multi-select-pro';
|
|
24
24
|
export { CountrySelect, getEmojiFlag } from './country-select';
|
|
25
25
|
export type { CountrySelectProps, CountrySelectVariant, CountryOption, TCountryCode } from './country-select';
|
|
26
|
-
export { LanguageSelect } from './language-select';
|
|
26
|
+
export { LanguageSelect, getLanguageFlag, LANGUAGE_TO_COUNTRY } from './language-select';
|
|
27
27
|
export type { LanguageSelectProps, LanguageSelectVariant, LanguageOption, TLanguageCode } from './language-select';
|
|
28
28
|
export { MultiSelectProAsync } from './multi-select-pro/async';
|
|
29
29
|
export type { MultiSelectProAsyncProps } from './multi-select-pro/async';
|
|
@@ -48,7 +48,7 @@ export type { PortalProps } from './portal';
|
|
|
48
48
|
// Overlay Components
|
|
49
49
|
export { Dialog, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription } from './dialog';
|
|
50
50
|
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from './alert-dialog';
|
|
51
|
-
export { Popover, PopoverContent, PopoverTrigger } from './popover';
|
|
51
|
+
export { Popover, PopoverContent, PopoverTrigger, PopoverAnchor, PopoverArrow } from './popover';
|
|
52
52
|
export { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from './sheet';
|
|
53
53
|
export { Drawer, DrawerTrigger, DrawerClose, DrawerContent, DrawerHeader, DrawerFooter, DrawerTitle, DrawerDescription } from './drawer';
|
|
54
54
|
export { ResponsiveSheet, ResponsiveSheetContent, ResponsiveSheetHeader, ResponsiveSheetTitle, ResponsiveSheetDescription, ResponsiveSheetFooter } from './responsive-sheet';
|
|
@@ -2,9 +2,274 @@
|
|
|
2
2
|
|
|
3
3
|
import { Check, ChevronsUpDown, Search, X } from 'lucide-react';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import { languages, type TLanguageCode } from 'countries-list';
|
|
5
|
+
import { languages, getEmojiFlag, type TLanguageCode, type TCountryCode } from 'countries-list';
|
|
6
6
|
|
|
7
7
|
import { cn } from '../lib/utils';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Mapping of language codes (ISO 639-1) to primary country codes (ISO 3166-1 alpha-2)
|
|
11
|
+
* Used to display country flag emoji for each language
|
|
12
|
+
*
|
|
13
|
+
* Note: Some languages are spoken in multiple countries, we pick the most representative one.
|
|
14
|
+
*/
|
|
15
|
+
const LANGUAGE_TO_COUNTRY: Partial<Record<TLanguageCode, TCountryCode>> = {
|
|
16
|
+
// Major world languages
|
|
17
|
+
en: 'US', // English → United States
|
|
18
|
+
zh: 'CN', // Chinese → China
|
|
19
|
+
es: 'ES', // Spanish → Spain
|
|
20
|
+
ar: 'SA', // Arabic → Saudi Arabia
|
|
21
|
+
hi: 'IN', // Hindi → India
|
|
22
|
+
bn: 'BD', // Bengali → Bangladesh
|
|
23
|
+
pt: 'BR', // Portuguese → Brazil
|
|
24
|
+
ru: 'RU', // Russian → Russia
|
|
25
|
+
ja: 'JP', // Japanese → Japan
|
|
26
|
+
de: 'DE', // German → Germany
|
|
27
|
+
fr: 'FR', // French → France
|
|
28
|
+
ko: 'KR', // Korean → South Korea
|
|
29
|
+
it: 'IT', // Italian → Italy
|
|
30
|
+
tr: 'TR', // Turkish → Turkey
|
|
31
|
+
vi: 'VN', // Vietnamese → Vietnam
|
|
32
|
+
pl: 'PL', // Polish → Poland
|
|
33
|
+
uk: 'UA', // Ukrainian → Ukraine
|
|
34
|
+
nl: 'NL', // Dutch → Netherlands
|
|
35
|
+
|
|
36
|
+
// European languages
|
|
37
|
+
el: 'GR', // Greek → Greece
|
|
38
|
+
cs: 'CZ', // Czech → Czech Republic
|
|
39
|
+
sv: 'SE', // Swedish → Sweden
|
|
40
|
+
hu: 'HU', // Hungarian → Hungary
|
|
41
|
+
ro: 'RO', // Romanian → Romania
|
|
42
|
+
da: 'DK', // Danish → Denmark
|
|
43
|
+
fi: 'FI', // Finnish → Finland
|
|
44
|
+
no: 'NO', // Norwegian → Norway
|
|
45
|
+
nb: 'NO', // Norwegian Bokmål → Norway
|
|
46
|
+
nn: 'NO', // Norwegian Nynorsk → Norway
|
|
47
|
+
sk: 'SK', // Slovak → Slovakia
|
|
48
|
+
bg: 'BG', // Bulgarian → Bulgaria
|
|
49
|
+
hr: 'HR', // Croatian → Croatia
|
|
50
|
+
sr: 'RS', // Serbian → Serbia
|
|
51
|
+
sl: 'SI', // Slovenian → Slovenia
|
|
52
|
+
et: 'EE', // Estonian → Estonia
|
|
53
|
+
lv: 'LV', // Latvian → Latvia
|
|
54
|
+
lt: 'LT', // Lithuanian → Lithuania
|
|
55
|
+
be: 'BY', // Belarusian → Belarus
|
|
56
|
+
mk: 'MK', // Macedonian → North Macedonia
|
|
57
|
+
sq: 'AL', // Albanian → Albania
|
|
58
|
+
is: 'IS', // Icelandic → Iceland
|
|
59
|
+
mt: 'MT', // Maltese → Malta
|
|
60
|
+
ga: 'IE', // Irish → Ireland
|
|
61
|
+
cy: 'GB', // Welsh → United Kingdom
|
|
62
|
+
gd: 'GB', // Scottish Gaelic → United Kingdom
|
|
63
|
+
br: 'FR', // Breton → France
|
|
64
|
+
lb: 'LU', // Luxembourgish → Luxembourg
|
|
65
|
+
fo: 'FO', // Faroese → Faroe Islands
|
|
66
|
+
bs: 'BA', // Bosnian → Bosnia
|
|
67
|
+
|
|
68
|
+
// Spanish regional
|
|
69
|
+
eu: 'ES', // Basque → Spain
|
|
70
|
+
ca: 'ES', // Catalan → Spain
|
|
71
|
+
gl: 'ES', // Galician → Spain
|
|
72
|
+
|
|
73
|
+
// Asian languages
|
|
74
|
+
th: 'TH', // Thai → Thailand
|
|
75
|
+
id: 'ID', // Indonesian → Indonesia
|
|
76
|
+
ms: 'MY', // Malay → Malaysia
|
|
77
|
+
tl: 'PH', // Tagalog → Philippines
|
|
78
|
+
jv: 'ID', // Javanese → Indonesia
|
|
79
|
+
su: 'ID', // Sundanese → Indonesia
|
|
80
|
+
|
|
81
|
+
// South Asian languages
|
|
82
|
+
ta: 'IN', // Tamil → India
|
|
83
|
+
te: 'IN', // Telugu → India
|
|
84
|
+
mr: 'IN', // Marathi → India
|
|
85
|
+
gu: 'IN', // Gujarati → India
|
|
86
|
+
kn: 'IN', // Kannada → India
|
|
87
|
+
ml: 'IN', // Malayalam → India
|
|
88
|
+
pa: 'IN', // Punjabi → India
|
|
89
|
+
or: 'IN', // Odia → India
|
|
90
|
+
as: 'IN', // Assamese → India
|
|
91
|
+
ne: 'NP', // Nepali → Nepal
|
|
92
|
+
si: 'LK', // Sinhala → Sri Lanka
|
|
93
|
+
dz: 'BT', // Dzongkha → Bhutan
|
|
94
|
+
|
|
95
|
+
// Middle East & Central Asia
|
|
96
|
+
fa: 'IR', // Persian/Farsi → Iran
|
|
97
|
+
ur: 'PK', // Urdu → Pakistan
|
|
98
|
+
ps: 'AF', // Pashto → Afghanistan
|
|
99
|
+
he: 'IL', // Hebrew → Israel
|
|
100
|
+
ku: 'IQ', // Kurdish → Iraq
|
|
101
|
+
hy: 'AM', // Armenian → Armenia
|
|
102
|
+
ka: 'GE', // Georgian → Georgia
|
|
103
|
+
az: 'AZ', // Azerbaijani → Azerbaijan
|
|
104
|
+
kk: 'KZ', // Kazakh → Kazakhstan
|
|
105
|
+
uz: 'UZ', // Uzbek → Uzbekistan
|
|
106
|
+
tg: 'TJ', // Tajik → Tajikistan
|
|
107
|
+
ky: 'KG', // Kyrgyz → Kyrgyzstan
|
|
108
|
+
tk: 'TM', // Turkmen → Turkmenistan
|
|
109
|
+
mn: 'MN', // Mongolian → Mongolia
|
|
110
|
+
|
|
111
|
+
// Southeast Asian
|
|
112
|
+
my: 'MM', // Burmese → Myanmar
|
|
113
|
+
km: 'KH', // Khmer → Cambodia
|
|
114
|
+
lo: 'LA', // Lao → Laos
|
|
115
|
+
|
|
116
|
+
// African languages
|
|
117
|
+
sw: 'KE', // Swahili → Kenya
|
|
118
|
+
am: 'ET', // Amharic → Ethiopia
|
|
119
|
+
ha: 'NG', // Hausa → Nigeria
|
|
120
|
+
yo: 'NG', // Yoruba → Nigeria
|
|
121
|
+
ig: 'NG', // Igbo → Nigeria
|
|
122
|
+
zu: 'ZA', // Zulu → South Africa
|
|
123
|
+
xh: 'ZA', // Xhosa → South Africa
|
|
124
|
+
af: 'ZA', // Afrikaans → South Africa
|
|
125
|
+
st: 'ZA', // Southern Sotho → South Africa
|
|
126
|
+
tn: 'BW', // Tswana → Botswana
|
|
127
|
+
sn: 'ZW', // Shona → Zimbabwe
|
|
128
|
+
rw: 'RW', // Kinyarwanda → Rwanda
|
|
129
|
+
rn: 'BI', // Kirundi → Burundi
|
|
130
|
+
so: 'SO', // Somali → Somalia
|
|
131
|
+
ti: 'ER', // Tigrinya → Eritrea
|
|
132
|
+
mg: 'MG', // Malagasy → Madagascar
|
|
133
|
+
ny: 'MW', // Chichewa → Malawi
|
|
134
|
+
lg: 'UG', // Luganda → Uganda
|
|
135
|
+
wo: 'SN', // Wolof → Senegal
|
|
136
|
+
ff: 'SN', // Fulah → Senegal
|
|
137
|
+
bm: 'ML', // Bambara → Mali
|
|
138
|
+
|
|
139
|
+
// Caribbean & Creole
|
|
140
|
+
ht: 'HT', // Haitian Creole → Haiti
|
|
141
|
+
|
|
142
|
+
// Pacific
|
|
143
|
+
mi: 'NZ', // Maori → New Zealand
|
|
144
|
+
sm: 'WS', // Samoan → Samoa
|
|
145
|
+
to: 'TO', // Tongan → Tonga
|
|
146
|
+
fj: 'FJ', // Fijian → Fiji
|
|
147
|
+
mh: 'MH', // Marshallese → Marshall Islands
|
|
148
|
+
ty: 'PF', // Tahitian → French Polynesia
|
|
149
|
+
na: 'NR', // Nauruan → Nauru
|
|
150
|
+
bi: 'VU', // Bislama → Vanuatu
|
|
151
|
+
ch: 'GU', // Chamorro → Guam
|
|
152
|
+
|
|
153
|
+
// Other constructed/historical
|
|
154
|
+
// Note: Constructed languages have no country, using symbolic mappings
|
|
155
|
+
// eo: Esperanto - no country flag available
|
|
156
|
+
la: 'VA', // Latin → Vatican
|
|
157
|
+
// ia: Interlingua - no country flag available
|
|
158
|
+
// ie: Interlingue - no country flag available
|
|
159
|
+
// io: Ido - no country flag available
|
|
160
|
+
// vo: Volapük - no country flag available
|
|
161
|
+
|
|
162
|
+
// China minority languages
|
|
163
|
+
bo: 'CN', // Tibetan → China
|
|
164
|
+
ug: 'CN', // Uyghur → China
|
|
165
|
+
za: 'CN', // Zhuang → China
|
|
166
|
+
ii: 'CN', // Sichuan Yi → China
|
|
167
|
+
|
|
168
|
+
// South Asia
|
|
169
|
+
dv: 'MV', // Dhivehi → Maldives
|
|
170
|
+
ks: 'IN', // Kashmiri → India
|
|
171
|
+
sd: 'PK', // Sindhi → Pakistan
|
|
172
|
+
sa: 'IN', // Sanskrit → India
|
|
173
|
+
pi: 'IN', // Pali → India (historical Buddhist)
|
|
174
|
+
|
|
175
|
+
// Baltic-Finnic
|
|
176
|
+
fy: 'NL', // Western Frisian → Netherlands
|
|
177
|
+
|
|
178
|
+
// Caucasian
|
|
179
|
+
os: 'RU', // Ossetic → Russia
|
|
180
|
+
ce: 'RU', // Chechen → Russia
|
|
181
|
+
av: 'RU', // Avar → Russia
|
|
182
|
+
ab: 'GE', // Abkhazian → Georgia
|
|
183
|
+
|
|
184
|
+
// Turkic in Russia
|
|
185
|
+
tt: 'RU', // Tatar → Russia
|
|
186
|
+
ba: 'RU', // Bashkir → Russia
|
|
187
|
+
cv: 'RU', // Chuvash → Russia
|
|
188
|
+
|
|
189
|
+
// Russia minority
|
|
190
|
+
kv: 'RU', // Komi → Russia
|
|
191
|
+
|
|
192
|
+
// Africa additional
|
|
193
|
+
aa: 'ET', // Afar → Ethiopia
|
|
194
|
+
ak: 'GH', // Akan → Ghana
|
|
195
|
+
ee: 'GH', // Ewe → Ghana
|
|
196
|
+
tw: 'GH', // Twi → Ghana
|
|
197
|
+
ln: 'CD', // Lingala → DR Congo
|
|
198
|
+
lu: 'CD', // Luba-Katanga → DR Congo
|
|
199
|
+
kg: 'CD', // Kongo → DR Congo
|
|
200
|
+
sg: 'CF', // Sango → Central African Republic
|
|
201
|
+
ki: 'KE', // Kikuyu → Kenya
|
|
202
|
+
om: 'ET', // Oromo → Ethiopia
|
|
203
|
+
kr: 'NE', // Kanuri → Niger
|
|
204
|
+
kj: 'NA', // Kuanyama → Namibia
|
|
205
|
+
hz: 'NA', // Herero → Namibia
|
|
206
|
+
ng: 'NA', // Ndonga → Namibia
|
|
207
|
+
nd: 'ZW', // North Ndebele → Zimbabwe
|
|
208
|
+
nr: 'ZA', // South Ndebele → South Africa
|
|
209
|
+
ss: 'SZ', // Swati → Eswatini (Swaziland)
|
|
210
|
+
ts: 'ZA', // Tsonga → South Africa
|
|
211
|
+
ve: 'ZA', // Venda → South Africa
|
|
212
|
+
|
|
213
|
+
// Americas indigenous
|
|
214
|
+
gn: 'PY', // Guarani → Paraguay
|
|
215
|
+
qu: 'PE', // Quechua → Peru
|
|
216
|
+
ay: 'BO', // Aymara → Bolivia
|
|
217
|
+
nv: 'US', // Navajo → United States
|
|
218
|
+
oj: 'CA', // Ojibwa → Canada
|
|
219
|
+
cr: 'CA', // Cree → Canada
|
|
220
|
+
iu: 'CA', // Inuktitut → Canada
|
|
221
|
+
ik: 'US', // Inupiak → United States (Alaska)
|
|
222
|
+
|
|
223
|
+
// Greenland
|
|
224
|
+
kl: 'GL', // Greenlandic → Greenland
|
|
225
|
+
|
|
226
|
+
// Other European
|
|
227
|
+
an: 'ES', // Aragonese → Spain
|
|
228
|
+
wa: 'BE', // Walloon → Belgium
|
|
229
|
+
li: 'NL', // Limburgian → Netherlands
|
|
230
|
+
|
|
231
|
+
// Slavic historical
|
|
232
|
+
cu: 'BG', // Old Church Slavonic → Bulgaria
|
|
233
|
+
mo: 'MD', // Moldovan → Moldova
|
|
234
|
+
|
|
235
|
+
// Jewish
|
|
236
|
+
yi: 'IL', // Yiddish → Israel
|
|
237
|
+
|
|
238
|
+
// Bihari (group)
|
|
239
|
+
bh: 'IN', // Bihari → India
|
|
240
|
+
|
|
241
|
+
// Papua New Guinea
|
|
242
|
+
ho: 'PG', // Hiri Motu → Papua New Guinea
|
|
243
|
+
|
|
244
|
+
// Other Slavic
|
|
245
|
+
sh: 'RS', // Serbo-Croatian → Serbia
|
|
246
|
+
|
|
247
|
+
// Romance
|
|
248
|
+
oc: 'FR', // Occitan → France
|
|
249
|
+
co: 'FR', // Corsican → France
|
|
250
|
+
sc: 'IT', // Sardinian → Italy
|
|
251
|
+
rm: 'CH', // Romansh → Switzerland
|
|
252
|
+
|
|
253
|
+
// Germanic
|
|
254
|
+
gv: 'IM', // Manx → Isle of Man
|
|
255
|
+
kw: 'GB', // Cornish → United Kingdom
|
|
256
|
+
|
|
257
|
+
// Uralic
|
|
258
|
+
se: 'NO', // Northern Sami → Norway
|
|
259
|
+
|
|
260
|
+
// Note: ch (Chamorro) already defined above in Pacific section
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Get emoji flag for a language code
|
|
265
|
+
* @param languageCode - ISO 639-1 language code (e.g., 'en', 'ru', 'ko')
|
|
266
|
+
* @returns Emoji flag string or empty string if no mapping exists
|
|
267
|
+
*/
|
|
268
|
+
export function getLanguageFlag(languageCode: TLanguageCode | string): string {
|
|
269
|
+
const countryCode = LANGUAGE_TO_COUNTRY[languageCode as TLanguageCode];
|
|
270
|
+
if (!countryCode) return '';
|
|
271
|
+
return getEmojiFlag(countryCode);
|
|
272
|
+
}
|
|
8
273
|
import { Badge } from './badge';
|
|
9
274
|
import { Button } from './button';
|
|
10
275
|
import { Checkbox } from './checkbox';
|
|
@@ -19,6 +284,8 @@ export interface LanguageOption {
|
|
|
19
284
|
code: TLanguageCode;
|
|
20
285
|
name: string;
|
|
21
286
|
native: string;
|
|
287
|
+
/** Emoji flag (if available) */
|
|
288
|
+
flag: string;
|
|
22
289
|
}
|
|
23
290
|
|
|
24
291
|
export type LanguageSelectVariant = 'dropdown' | 'inline';
|
|
@@ -52,6 +319,10 @@ export interface LanguageSelectProps {
|
|
|
52
319
|
allowedLanguages?: TLanguageCode[];
|
|
53
320
|
/** Exclude specific language codes */
|
|
54
321
|
excludedLanguages?: TLanguageCode[];
|
|
322
|
+
/** Show flag emoji (default: true) */
|
|
323
|
+
showFlag?: boolean;
|
|
324
|
+
/** Show language code (default: false) */
|
|
325
|
+
showCode?: boolean;
|
|
55
326
|
/** Max height for inline variant */
|
|
56
327
|
maxHeight?: number;
|
|
57
328
|
/** Show search input */
|
|
@@ -125,6 +396,8 @@ export function LanguageSelect({
|
|
|
125
396
|
showNativeName = false,
|
|
126
397
|
allowedLanguages,
|
|
127
398
|
excludedLanguages,
|
|
399
|
+
showFlag = true,
|
|
400
|
+
showCode = false,
|
|
128
401
|
maxHeight = 300,
|
|
129
402
|
showSearch = true,
|
|
130
403
|
selectedCountLabel = (count: number) => `${count} selected`,
|
|
@@ -155,6 +428,7 @@ export function LanguageSelect({
|
|
|
155
428
|
code,
|
|
156
429
|
name: getLanguageName?.(code) ?? languages[code].name,
|
|
157
430
|
native: languages[code].native,
|
|
431
|
+
flag: getLanguageFlag(code),
|
|
158
432
|
}))
|
|
159
433
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
160
434
|
}, [getLanguageName, allowedLanguages, excludedLanguages]);
|
|
@@ -231,8 +505,17 @@ export function LanguageSelect({
|
|
|
231
505
|
filteredLanguages.map((language) => {
|
|
232
506
|
const isSelected = value.includes(language.code);
|
|
233
507
|
return (
|
|
234
|
-
<
|
|
508
|
+
<div
|
|
235
509
|
key={language.code}
|
|
510
|
+
role="button"
|
|
511
|
+
tabIndex={disabled ? -1 : 0}
|
|
512
|
+
onClick={() => !disabled && handleSelect(language.code)}
|
|
513
|
+
onKeyDown={(e) => {
|
|
514
|
+
if (!disabled && (e.key === 'Enter' || e.key === ' ')) {
|
|
515
|
+
e.preventDefault();
|
|
516
|
+
handleSelect(language.code);
|
|
517
|
+
}
|
|
518
|
+
}}
|
|
236
519
|
className={cn(
|
|
237
520
|
'flex items-center gap-3 px-3 py-2 rounded-md cursor-pointer',
|
|
238
521
|
'hover:bg-accent/50 transition-colors',
|
|
@@ -245,6 +528,7 @@ export function LanguageSelect({
|
|
|
245
528
|
checked={isSelected}
|
|
246
529
|
onCheckedChange={() => !disabled && handleSelect(language.code)}
|
|
247
530
|
disabled={disabled}
|
|
531
|
+
onClick={(e) => e.stopPropagation()}
|
|
248
532
|
/>
|
|
249
533
|
) : (
|
|
250
534
|
<div className={cn(
|
|
@@ -254,6 +538,9 @@ export function LanguageSelect({
|
|
|
254
538
|
{isSelected && <div className="h-2 w-2 rounded-full bg-primary-foreground" />}
|
|
255
539
|
</div>
|
|
256
540
|
)}
|
|
541
|
+
{showFlag && language.flag && (
|
|
542
|
+
<span className="text-lg">{language.flag}</span>
|
|
543
|
+
)}
|
|
257
544
|
<div className="flex flex-col flex-1 min-w-0">
|
|
258
545
|
<span className={cn('text-sm', isSelected && 'font-medium')}>
|
|
259
546
|
{language.name}
|
|
@@ -264,10 +551,12 @@ export function LanguageSelect({
|
|
|
264
551
|
</span>
|
|
265
552
|
)}
|
|
266
553
|
</div>
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
554
|
+
{showCode && (
|
|
555
|
+
<span className="text-xs text-muted-foreground uppercase">
|
|
556
|
+
{language.code}
|
|
557
|
+
</span>
|
|
558
|
+
)}
|
|
559
|
+
</div>
|
|
271
560
|
);
|
|
272
561
|
})
|
|
273
562
|
)}
|
|
@@ -287,7 +576,8 @@ export function LanguageSelect({
|
|
|
287
576
|
const language = selectedLanguages[0]!;
|
|
288
577
|
return (
|
|
289
578
|
<div className="flex items-center gap-2">
|
|
290
|
-
|
|
579
|
+
{showFlag && language.flag && <span>{language.flag}</span>}
|
|
580
|
+
{showCode && <span className="text-xs text-muted-foreground uppercase">{language.code}</span>}
|
|
291
581
|
<span>{language.name}</span>
|
|
292
582
|
</div>
|
|
293
583
|
);
|
|
@@ -304,7 +594,8 @@ export function LanguageSelect({
|
|
|
304
594
|
variant="secondary"
|
|
305
595
|
className="mr-1 text-xs"
|
|
306
596
|
>
|
|
307
|
-
<span className="mr-1
|
|
597
|
+
{showFlag && language.flag && <span className="mr-1">{language.flag}</span>}
|
|
598
|
+
{showCode && <span className="mr-1 text-muted-foreground uppercase">{language.code}</span>}
|
|
308
599
|
{language.name}
|
|
309
600
|
<button
|
|
310
601
|
className="ml-1 rounded-full hover:bg-muted-foreground/20"
|
|
@@ -323,7 +614,7 @@ export function LanguageSelect({
|
|
|
323
614
|
)}
|
|
324
615
|
</div>
|
|
325
616
|
)
|
|
326
|
-
}, [selectedLanguages, maxDisplay, resolvedPlaceholder, disabled, multiple, handleRemove, moreItemsLabel])
|
|
617
|
+
}, [selectedLanguages, maxDisplay, resolvedPlaceholder, disabled, multiple, handleRemove, moreItemsLabel, showFlag, showCode])
|
|
327
618
|
|
|
328
619
|
return (
|
|
329
620
|
<Popover
|
|
@@ -379,6 +670,9 @@ export function LanguageSelect({
|
|
|
379
670
|
isSelected ? "opacity-100" : "opacity-0"
|
|
380
671
|
)}
|
|
381
672
|
/>
|
|
673
|
+
{showFlag && language.flag && (
|
|
674
|
+
<span className="mr-2 text-lg">{language.flag}</span>
|
|
675
|
+
)}
|
|
382
676
|
<div className="flex flex-col flex-1 min-w-0">
|
|
383
677
|
<span className="truncate">{language.name}</span>
|
|
384
678
|
{showNativeName && language.native !== language.name && (
|
|
@@ -387,9 +681,11 @@ export function LanguageSelect({
|
|
|
387
681
|
</span>
|
|
388
682
|
)}
|
|
389
683
|
</div>
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
684
|
+
{showCode && (
|
|
685
|
+
<span className="text-xs text-muted-foreground uppercase ml-2">
|
|
686
|
+
{language.code}
|
|
687
|
+
</span>
|
|
688
|
+
)}
|
|
393
689
|
</CommandItem>
|
|
394
690
|
)
|
|
395
691
|
})}
|
|
@@ -404,3 +700,4 @@ export function LanguageSelect({
|
|
|
404
700
|
|
|
405
701
|
// Re-export types for convenience
|
|
406
702
|
export type { TLanguageCode } from 'countries-list';
|
|
703
|
+
export { LANGUAGE_TO_COUNTRY };
|
|
@@ -31,4 +31,16 @@ const PopoverContent = React.forwardRef<
|
|
|
31
31
|
))
|
|
32
32
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
const PopoverArrow = React.forwardRef<
|
|
35
|
+
React.ElementRef<typeof PopoverPrimitive.Arrow>,
|
|
36
|
+
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Arrow>
|
|
37
|
+
>(({ className, ...props }, ref) => (
|
|
38
|
+
<PopoverPrimitive.Arrow
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={cn('fill-popover', className)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
))
|
|
44
|
+
PopoverArrow.displayName = PopoverPrimitive.Arrow.displayName
|
|
45
|
+
|
|
46
|
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverArrow }
|