From 3b989212cb0eca1f72cccf32cf5464f4251c8eae Mon Sep 17 00:00:00 2001 From: Utsav Luintel Date: Tue, 6 Jan 2026 15:00:59 +0545 Subject: [PATCH 1/9] refactor(ui/country): update component logic --- packages/ui/src/CountryDisplay/index.tsx | 36 ++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/ui/src/CountryDisplay/index.tsx b/packages/ui/src/CountryDisplay/index.tsx index 82ba38d3d..b24b802a9 100644 --- a/packages/ui/src/CountryDisplay/index.tsx +++ b/packages/ui/src/CountryDisplay/index.tsx @@ -2,17 +2,31 @@ import React, { useMemo } from "react"; import englishData from "../FormWidgets/CountryPicker/en.json"; -type I18nData = Record>; +export type Translation = Record; +export type LocalesData = Record; export interface CountryDisplayProperties { className?: string; code: string; fallbackLocale?: string; - i18n?: I18nData; + i18n?: LocalesData; locale?: string; showFlag?: boolean; } +const determineFallback = ( + locales: LocalesData | undefined, + fallbackLocale: string, +): Translation | null => { + if (locales?.[fallbackLocale]) { + return locales[fallbackLocale]; + } + if (fallbackLocale === "en") { + return englishData as Translation; + } + return null; +}; + export const Country: React.FC = ({ className = "", code, @@ -21,21 +35,21 @@ export const Country: React.FC = ({ locale = "en", showFlag = true, }) => { - const countryLabel = useMemo(() => { - const countryCode = code?.trim().toUpperCase(); + const countryCode = code?.trim(); + const countryLabel = useMemo(() => { if (!countryCode) { - return; + return undefined; } + const fallbackData = determineFallback(i18n, fallbackLocale); + return ( i18n?.[locale]?.[countryCode] || - i18n?.[fallbackLocale]?.[countryCode] || - (englishData as Record)[countryCode] + fallbackData?.[countryCode] || + countryCode ); - }, [code, locale, fallbackLocale, i18n]); - - const countryCode = code.trim(); + }, [countryCode, locale, fallbackLocale, i18n]); return ( = ({ {showFlag && countryLabel && ( )} {countryLabel ?? "-"} From 3ab314aecd80bf4e026873761864415fa6da4f23 Mon Sep 17 00:00:00 2001 From: Utsav Luintel Date: Wed, 7 Jan 2026 16:48:39 +0545 Subject: [PATCH 2/9] feat: add renderOption prop to Country --- packages/ui/src/CountryDisplay/index.tsx | 35 +++++++++--------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/packages/ui/src/CountryDisplay/index.tsx b/packages/ui/src/CountryDisplay/index.tsx index b24b802a9..c51c267e5 100644 --- a/packages/ui/src/CountryDisplay/index.tsx +++ b/packages/ui/src/CountryDisplay/index.tsx @@ -1,39 +1,26 @@ import React, { useMemo } from "react"; -import englishData from "../FormWidgets/CountryPicker/en.json"; - -export type Translation = Record; -export type LocalesData = Record; +import { Locales } from "../FormWidgets/CountryPicker"; +import { getFallbackTranslation } from "../utils/CountryPicker"; export interface CountryDisplayProperties { className?: string; code: string; fallbackLocale?: string; - i18n?: LocalesData; + locales?: Locales; locale?: string; showFlag?: boolean; + renderOption?: (code: string, label: string) => React.ReactNode; } -const determineFallback = ( - locales: LocalesData | undefined, - fallbackLocale: string, -): Translation | null => { - if (locales?.[fallbackLocale]) { - return locales[fallbackLocale]; - } - if (fallbackLocale === "en") { - return englishData as Translation; - } - return null; -}; - export const Country: React.FC = ({ className = "", code, fallbackLocale = "en", - i18n = {}, + locales = {}, locale = "en", showFlag = true, + renderOption, }) => { const countryCode = code?.trim(); @@ -42,14 +29,18 @@ export const Country: React.FC = ({ return undefined; } - const fallbackData = determineFallback(i18n, fallbackLocale); + const fallbackData = getFallbackTranslation(fallbackLocale, locales); return ( - i18n?.[locale]?.[countryCode] || + locales?.[locale]?.[countryCode] || fallbackData?.[countryCode] || countryCode ); - }, [countryCode, locale, fallbackLocale, i18n]); + }, [countryCode, locale, fallbackLocale, locales]); + + if (renderOption && countryCode && countryLabel) { + return <>{renderOption(countryCode, countryLabel)}; + } return ( Date: Thu, 8 Jan 2026 15:32:33 +0545 Subject: [PATCH 3/9] feat(ui/country): add flag related props --- .../CountryDisplay/CountryDisplayDemo.tsx | 136 +++++++++++++++--- .../Ui/components/CountryDisplay/en.json | 3 +- apps/demo/src/locales/en/ui.json | 8 ++ apps/demo/src/locales/fr/ui.json | 8 ++ packages/ui/src/CountryDisplay/index.tsx | 65 +++++++-- .../ui/src/assets/css/country-display.css | 38 ++++- 6 files changed, 222 insertions(+), 36 deletions(-) diff --git a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx index 9a502c898..766c2785c 100644 --- a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx +++ b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx @@ -13,6 +13,10 @@ export const CountryDisplayDemo = () => { const navigate = useNavigate(); const selectedLocale = i18n.language; + const customFlagsPath = (code: string) => { + return `https://flagcdn.com/${code.toLowerCase().trim()}.svg`; + }; + const data = [ { id: 1, @@ -37,20 +41,48 @@ export const CountryDisplayDemo = () => { }, { id: 4, - prop: "i18n", - type: "Record>", - default: "{}", - description: t("countryDisplay.propertiesDescription.i18n"), + prop: "flagsPath", + type: "(code: string) => string", + default: "undefined", + description: t("countryDisplay.propertiesDescription.flagsPath"), }, { id: 5, + prop: "flagsPosition", + type: '"left" | "right" | "right-edge"', + default: '"left"', + description: t("countryDisplay.propertiesDescription.flagsPosition"), + }, + { + id: 6, + prop: "flagsStyle", + type: '"circle" | "rectangular" | "square"', + default: '"rectangular"', + description: t("countryDisplay.propertiesDescription.flagsStyle"), + }, + { + id: 7, prop: "locale", type: "string", default: "en", description: t("countryDisplay.propertiesDescription.locale"), }, { - id: 6, + id: 8, + prop: "locales", + type: "Record>", + default: "{}", + description: t("countryDisplay.propertiesDescription.i18n"), + }, + { + id: 9, + prop: "renderOption", + type: "(code: string, label: string) => ReactNode", + default: "undefined", + description: t("countryDisplay.propertiesDescription.renderOption"), + }, + { + id: 10, prop: "showFlag", type: "boolean", default: "true", @@ -84,7 +116,7 @@ export const CountryDisplayDemo = () => { @@ -98,8 +130,8 @@ const selectedLocale = "np"; ' /> @@ -107,8 +139,8 @@ const selectedLocale = "np";
@@ -129,8 +161,8 @@ selectedLocale = i18n.language + + +
+ + +
+ +
+ + +
+ +
+ +
+
+ ( +
+ + {label} +
+ )} + /> + + ( +
+ + {label} +
+ )} +/>`} + /> +
+
Country @@ -196,22 +290,20 @@ fallbackLocale = np;
>; + exampleCode={`type Locales = Record>; interface CountryDisplayProperties { code: string; className?: string; - fallbackLocale?: string; - i18n?: I18nData; + fallbackLocale?: string; + flagsPath?: (code: string) => string; + flagsPosition?: "left" | "right" | "right-edge"; + flagsStyle?: "circle" | "rectangular" | "square"; locale?: string; + locales?: I18nData; showFlag?: boolean; + renderOption?: (code: string, label: string) => React.ReactNode; } - -Example I18n: - { - en:{ "US": "USA" }, - fr: { "US": "États-Unis" } - } `} />
diff --git a/apps/demo/src/Views/Ui/components/CountryDisplay/en.json b/apps/demo/src/Views/Ui/components/CountryDisplay/en.json index 0ede55dc1..07fdeb387 100644 --- a/apps/demo/src/Views/Ui/components/CountryDisplay/en.json +++ b/apps/demo/src/Views/Ui/components/CountryDisplay/en.json @@ -8,5 +8,6 @@ "ES": "Spain", "IT": "Italy", "JP": "Japan", - "CN": "China" + "CN": "China", + "EG": "Egypt" } diff --git a/apps/demo/src/locales/en/ui.json b/apps/demo/src/locales/en/ui.json index 925ad50e5..9dfc09694 100644 --- a/apps/demo/src/locales/en/ui.json +++ b/apps/demo/src/locales/en/ui.json @@ -106,8 +106,11 @@ }, "countryDisplay": { "basic": "Basic", + "customFlagsPath": "Custom flag path", "customLocale": "New locale support", "fallback": "Fallback locale", + "flagsPosition": "Flag position", + "flagsStyle": "Flag style", "label": "Label", "locale": "Locales support", "notFound": "Missing country code", @@ -115,10 +118,15 @@ "code": "The ISO country code to display (e.g., 'US', 'gb').", "className": "CSS class to append to the wrapper span.", "fallbackLocale": "Locale to use if the specific translation is missing.", + "flagsPath": "Custom function to resolve image paths for flags.", + "flagsPosition": "Position of the flag relative to text ('left', 'right', 'right-edge').", + "flagsStyle": "Shape style of the flag ('circle', 'rectangular', 'square').", "i18n": "External translation dictionary for additional languages.", "locale": "The target locale for translation (e.g., 'en', 'fr').", + "renderOption": "Function to customize rendering: (code, label, flagElement) => ReactNode.", "showFlag": "If false, the flag will not be displayed." }, + "renderOption": "Custom render option", "showFlag": "Flag visibility", "title": "Country", "typeDefinitions": "Types" diff --git a/apps/demo/src/locales/fr/ui.json b/apps/demo/src/locales/fr/ui.json index 9a8f1ab24..55678b2cd 100644 --- a/apps/demo/src/locales/fr/ui.json +++ b/apps/demo/src/locales/fr/ui.json @@ -106,8 +106,11 @@ }, "countryDisplay": { "basic": "Basic (fr)", + "customFlagsPath": "Custom flag path (fr)", "customLocale": "New locale support (fr)", "fallback": "Fallback locale (fr)", + "flagsPosition": "Flag position (fr)", + "flagsStyle": "Flag style (fr)", "label": "Label (fr)", "locale": "Locales support (fr)", "notFound": "Missing country code (fr)", @@ -115,10 +118,15 @@ "code": "The ISO country code to display (e.g., 'US', 'gb'). (fr)", "className": "CSS class to append to the wrapper span. (fr)", "fallbackLocale": "Locale to use if the specific translation is missing. (fr)", + "flagsPath": "Custom function to resolve image paths for flags. (fr)", + "flagsPosition": "Position of the flag relative to text ('left', 'right', 'right-edge'). (fr)", + "flagsStyle": "Shape style of the flag ('circle', 'rectangular', 'square'). (fr)", "i18n": "External translation dictionary for additional languages. (fr)", "locale": "The target locale for translation (e.g., 'en', 'fr'). (fr)", + "renderOption": "Function to customize rendering: (code, label, flagElement) => ReactNode. (fr)", "showFlag": "If false, the flag will not be displayed. (fr)" }, + "renderOption": "Custom render option (fr)", "showFlag": "Flag visibility (fr)", "title": "Country (fr)", "typeDefinitions": "Types (fr)" diff --git a/packages/ui/src/CountryDisplay/index.tsx b/packages/ui/src/CountryDisplay/index.tsx index c51c267e5..13536a4b0 100644 --- a/packages/ui/src/CountryDisplay/index.tsx +++ b/packages/ui/src/CountryDisplay/index.tsx @@ -3,22 +3,44 @@ import React, { useMemo } from "react"; import { Locales } from "../FormWidgets/CountryPicker"; import { getFallbackTranslation } from "../utils/CountryPicker"; -export interface CountryDisplayProperties { +interface CountryDisplayProperties { className?: string; code: string; fallbackLocale?: string; - locales?: Locales; + flagsPath?: (code: string) => string; + flagsPosition?: "left" | "right" | "right-edge"; + flagsStyle?: "circle" | "rectangular" | "square"; locale?: string; + locales?: Locales; showFlag?: boolean; renderOption?: (code: string, label: string) => React.ReactNode; } +const getFlagClass = ( + code: string | undefined, + position: string, + style: string, +) => + [ + "flag-icon", + code && `flag-icon-${code.trim().toLowerCase()}`, + position === "right" && "flag-icon-right", + position === "right-edge" && "flag-icon-right-edge", + style === "circle" && "flag-icon-rounded", + style === "square" && "flag-icon-squared", + ] + .filter(Boolean) + .join(" "); + export const Country: React.FC = ({ className = "", code, fallbackLocale = "en", - locales = {}, + flagsPath, + flagsPosition = "left", + flagsStyle = "rectangular", locale = "en", + locales = {}, showFlag = true, renderOption, }) => { @@ -29,11 +51,11 @@ export const Country: React.FC = ({ return undefined; } - const fallbackData = getFallbackTranslation(fallbackLocale, locales); + const fallbackTranslation = getFallbackTranslation(fallbackLocale, locales); return ( locales?.[locale]?.[countryCode] || - fallbackData?.[countryCode] || + fallbackTranslation?.[countryCode] || countryCode ); }, [countryCode, locale, fallbackLocale, locales]); @@ -42,17 +64,36 @@ export const Country: React.FC = ({ return <>{renderOption(countryCode, countryLabel)}; } + const flagClass = useMemo( + () => getFlagClass(countryCode, flagsPosition, flagsStyle), + [countryCode, flagsPosition, flagsStyle], + ); + + const flagElement = useMemo(() => { + if (!showFlag || !countryCode) { + return null; + } + + if (flagsPath) { + return ( + {countryLabel} + ); + } + + return ; + }, [showFlag, countryCode, countryLabel, flagClass, flagsPath]); + return ( - {showFlag && countryLabel && ( - - )} + {flagElement} {countryLabel ?? "-"} ); diff --git a/packages/ui/src/assets/css/country-display.css b/packages/ui/src/assets/css/country-display.css index fd06c99cd..38006efc7 100644 --- a/packages/ui/src/assets/css/country-display.css +++ b/packages/ui/src/assets/css/country-display.css @@ -2,16 +2,52 @@ align-items: center; display: inline-flex; width: 100%; + vertical-align: middle; +} + +.country.is-code-only .flag-icon { + display: none; } .country-label { display: block; - flex: 1; + flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + order: 1; } .flag-icon { margin-right: 0.5rem; + order: 0; + flex-shrink: 0; + background-size: cover; + background-position: center; + min-width: 1.33em; + line-height: 1em; +} + +.flag-icon-right { + margin-right: 0; + margin-left: 0.5rem; + order: 2; +} + +.flag-icon-right-edge { + margin-right: 0; + margin-left: auto; + order: 2; +} + +.flag-icon-rounded { + border-radius: 50%; + aspect-ratio: 1/1; + object-fit: cover; +} + +.flag-icon-squared { + border-radius: 0; + aspect-ratio: 1/1; + object-fit: cover; } From 2aefe0a59741c312305d3cb14b537395b3d274f9 Mon Sep 17 00:00:00 2001 From: Utsav Luintel Date: Thu, 8 Jan 2026 17:27:14 +0545 Subject: [PATCH 4/9] refactor(ui/country): move country types to types folder --- packages/ui/src/CountryDisplay/index.tsx | 23 ++++++------- .../src/FormWidgets/CountryPicker/index.tsx | 34 ++++--------------- packages/ui/src/types/country-picker.ts | 29 ++++++++++++++++ packages/ui/src/types/index.ts | 2 ++ packages/ui/src/utils/CountryPicker.ts | 6 ++-- 5 files changed, 51 insertions(+), 43 deletions(-) create mode 100644 packages/ui/src/types/country-picker.ts diff --git a/packages/ui/src/CountryDisplay/index.tsx b/packages/ui/src/CountryDisplay/index.tsx index 13536a4b0..99bb120ed 100644 --- a/packages/ui/src/CountryDisplay/index.tsx +++ b/packages/ui/src/CountryDisplay/index.tsx @@ -1,8 +1,9 @@ import React, { useMemo } from "react"; -import { Locales } from "../FormWidgets/CountryPicker"; import { getFallbackTranslation } from "../utils/CountryPicker"; +import type { Locales } from "../types"; + interface CountryDisplayProperties { className?: string; code: string; @@ -48,7 +49,7 @@ export const Country: React.FC = ({ const countryLabel = useMemo(() => { if (!countryCode) { - return undefined; + return; } const fallbackTranslation = getFallbackTranslation(fallbackLocale, locales); @@ -60,17 +61,13 @@ export const Country: React.FC = ({ ); }, [countryCode, locale, fallbackLocale, locales]); - if (renderOption && countryCode && countryLabel) { - return <>{renderOption(countryCode, countryLabel)}; - } - const flagClass = useMemo( () => getFlagClass(countryCode, flagsPosition, flagsStyle), [countryCode, flagsPosition, flagsStyle], ); - const flagElement = useMemo(() => { - if (!showFlag || !countryCode) { + const getFlagElement = () => { + if (!showFlag || !countryCode || countryLabel === countryCode) { return null; } @@ -86,14 +83,16 @@ export const Country: React.FC = ({ } return ; - }, [showFlag, countryCode, countryLabel, flagClass, flagsPath]); + }; - return ( + return renderOption && countryCode && countryLabel ? ( + <>{renderOption(countryCode, countryLabel)} + ) : ( - {flagElement} + {getFlagElement()} {countryLabel ?? "-"} ); diff --git a/packages/ui/src/FormWidgets/CountryPicker/index.tsx b/packages/ui/src/FormWidgets/CountryPicker/index.tsx index 7fd01c325..f63e002c2 100644 --- a/packages/ui/src/FormWidgets/CountryPicker/index.tsx +++ b/packages/ui/src/FormWidgets/CountryPicker/index.tsx @@ -4,36 +4,14 @@ import { getFallbackTranslation } from "../../utils/CountryPicker"; import { Select, ISelectProperties } from "../Select"; import defaultGroups from "./groups.json"; +import type { + Locales, + Groups, + CountryPickerLabels, + CountryPickerProperties, +} from "../../types"; import type { Option } from "../Select"; -export type Translation = Record; -export type Locales = Record; -export type Groups = Record; - -export type CountryPickerLabels = { - favorites?: string; - allCountries?: string; -}; - -export type CountryPickerProperties = Omit< - ISelectProperties, - "options" -> & { - exclude?: string[]; - fallbackLocale?: string; - favorites?: string[]; - flags?: boolean; - flagsPath?: (code: string) => string; - flagsPosition?: "left" | "right" | "right-edge"; - flagsStyle?: "circle" | "rectangular" | "square"; - groups?: Groups; - include?: string[]; - includeFavorites?: boolean; - labels?: CountryPickerLabels; - locale?: string; - locales?: Locales; -}; - export { defaultGroups }; const getBaseOptions = ( diff --git a/packages/ui/src/types/country-picker.ts b/packages/ui/src/types/country-picker.ts new file mode 100644 index 000000000..aa6213e48 --- /dev/null +++ b/packages/ui/src/types/country-picker.ts @@ -0,0 +1,29 @@ +import { ISelectProperties } from "../FormWidgets"; + +export type Translation = Record; +export type Locales = Record; +export type Groups = Record; + +export type CountryPickerLabels = { + favorites?: string; + allCountries?: string; +}; + +export type CountryPickerProperties = Omit< + ISelectProperties, + "options" +> & { + exclude?: string[]; + fallbackLocale?: string; + favorites?: string[]; + flags?: boolean; + flagsPath?: (code: string) => string; + flagsPosition?: "left" | "right" | "right-edge"; + flagsStyle?: "circle" | "rectangular" | "square"; + groups?: Groups; + include?: string[]; + includeFavorites?: boolean; + labels?: CountryPickerLabels; + locale?: string; + locales?: Locales; +}; diff --git a/packages/ui/src/types/index.ts b/packages/ui/src/types/index.ts index 44f4886f7..3d62846ea 100644 --- a/packages/ui/src/types/index.ts +++ b/packages/ui/src/types/index.ts @@ -1,4 +1,6 @@ export * from "./menu"; +export * from "./country-picker"; + import type { NavGroupDisplayMode, NavGroupType, diff --git a/packages/ui/src/utils/CountryPicker.ts b/packages/ui/src/utils/CountryPicker.ts index 4ba824b3b..ccddb5920 100644 --- a/packages/ui/src/utils/CountryPicker.ts +++ b/packages/ui/src/utils/CountryPicker.ts @@ -1,5 +1,5 @@ -import defaultEnglishCatalogue from "../FormWidgets/CountryPicker/en.json"; -import { Translation, Locales } from "../FormWidgets/CountryPicker/index"; +import defaultEnglishTranslation from "../FormWidgets/CountryPicker/en.json"; +import { Translation, Locales } from "../types"; export const getFallbackTranslation = ( fallbackLocale: string, @@ -10,7 +10,7 @@ export const getFallbackTranslation = ( } if (fallbackLocale === "en") { - return defaultEnglishCatalogue; + return defaultEnglishTranslation; } return null; From 54ba521d504d3ff3b224fa8555b811fc6a64ead6 Mon Sep 17 00:00:00 2001 From: Utsav Luintel Date: Thu, 8 Jan 2026 17:37:10 +0545 Subject: [PATCH 5/9] refactor(ui/country): manage css --- .../CountryDisplay/CountryDisplayDemo.tsx | 20 +++++-------------- apps/demo/src/assets/css/country.css | 12 +++++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx index 766c2785c..a83a689fe 100644 --- a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx +++ b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx @@ -212,19 +212,7 @@ fallbackLocale = np; ( -
+
@@ -234,10 +222,12 @@ fallbackLocale = np; /> ( -
+
{label}
diff --git a/apps/demo/src/assets/css/country.css b/apps/demo/src/assets/css/country.css index 7e2826a9d..7e1c0f1a9 100644 --- a/apps/demo/src/assets/css/country.css +++ b/apps/demo/src/assets/css/country.css @@ -3,3 +3,15 @@ flex-direction: column; gap: 0.25rem; } + +.custom-style { + display: inline-flex; + align-items: center; + gap: 8px; + background: #eef2ff; + padding: 4px 12px; + border-radius: 20px; + border: 1px solid #c7d2fe; + color: #3730a3; + width: 8rem; +} \ No newline at end of file From e68a308d2b615489d1558c7977997fe91206479c Mon Sep 17 00:00:00 2001 From: Utsav Luintel Date: Thu, 8 Jan 2026 19:28:58 +0545 Subject: [PATCH 6/9] refactor(ui/country): change css --- .../CountryDisplay/CountryDisplayDemo.tsx | 10 +++++----- packages/ui/src/CountryDisplay/index.tsx | 2 +- packages/ui/src/assets/css/country-display.css | 15 ++------------- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx index a83a689fe..a77c3faec 100644 --- a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx +++ b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx @@ -184,6 +184,11 @@ fallbackLocale = np; /> +
+ + +
+
@@ -244,11 +249,6 @@ fallbackLocale = np;
-
- - -
-
= ({ }; return renderOption && countryCode && countryLabel ? ( - <>{renderOption(countryCode, countryLabel)} + renderOption(countryCode, countryLabel) ) : ( Date: Mon, 12 Jan 2026 12:43:41 +0545 Subject: [PATCH 7/9] refactor(ui/country): update demo --- .../CountryDisplay/CountryDisplayDemo.tsx | 38 +++++++++++++++++-- apps/demo/src/locales/en/ui.json | 12 +++++- apps/demo/src/locales/fr/ui.json | 10 +++++ packages/ui/src/utils/CountryPicker.ts | 3 +- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx index a77c3faec..c6b2102c3 100644 --- a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx +++ b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx @@ -190,13 +190,43 @@ fallbackLocale = np;
- - +
+

{t("countryDisplay.styles.rectangular")}

+ + +
+ +
+

{t("countryDisplay.styles.square")}

+ + +
+ +
+

{t("countryDisplay.styles.circle")}

+ + +
- - +
+

{t("countryDisplay.positions.left")}

+ + +
+ +
+

{t("countryDisplay.positions.right")}

+ + +
+ +
+

{t("countryDisplay.positions.rightEdge")}

+ + +
diff --git a/apps/demo/src/locales/en/ui.json b/apps/demo/src/locales/en/ui.json index b3e73dc71..3ee9c0d53 100644 --- a/apps/demo/src/locales/en/ui.json +++ b/apps/demo/src/locales/en/ui.json @@ -114,6 +114,11 @@ "label": "Label", "locale": "Locales support", "notFound": "Missing country code", + "positions": { + "left": "Left (default)", + "right": "Right", + "rightEdge": "Right edge" + }, "propertiesDescription": { "code": "The ISO country code to display (e.g., 'US', 'gb').", "className": "CSS class to append to the wrapper span.", @@ -128,6 +133,11 @@ }, "renderOption": "Custom render option", "showFlag": "Flag visibility", + "styles": { + "circle": "Circle", + "rectangular": "Rectangular (default)", + "square": "Square" + }, "title": "Country", "typeDefinitions": "Types" }, @@ -155,7 +165,7 @@ "single": "Select a country..." }, "propertiesDescription": { - "autoSortOptions":"By default, options are sorted alphabetically. If false, countries are sorted by priority in the order groups → favorites → include → fallback-locale translations, preserving the defined order.", + "autoSortOptions": "By default, options are sorted alphabetically. If false, countries are sorted by priority in the order groups → favorites → include → fallback-locale translations, preserving the defined order.", "data": "Custom country data to overwrite existing entries or add new ones.", "exclude": "An array of country codes to remove from the list.", "fallbackLocale": "Locale used when active locale translation is missing.", diff --git a/apps/demo/src/locales/fr/ui.json b/apps/demo/src/locales/fr/ui.json index c676c4758..b14f896e9 100644 --- a/apps/demo/src/locales/fr/ui.json +++ b/apps/demo/src/locales/fr/ui.json @@ -114,6 +114,11 @@ "label": "Label (fr)", "locale": "Locales support (fr)", "notFound": "Missing country code (fr)", + "positions": { + "left": "Left (default) (fr)", + "right": "Right (fr)", + "rightEdge": "Right edge (fr)" + }, "propertiesDescription": { "code": "The ISO country code to display (e.g., 'US', 'gb'). (fr)", "className": "CSS class to append to the wrapper span. (fr)", @@ -128,6 +133,11 @@ }, "renderOption": "Custom render option (fr)", "showFlag": "Flag visibility (fr)", + "styles": { + "circle": "Circle (fr)", + "rectangular": "Rectangular (default) (fr)", + "square": "Square (fr)" + }, "title": "Country (fr)", "typeDefinitions": "Types (fr)" }, diff --git a/packages/ui/src/utils/CountryPicker.ts b/packages/ui/src/utils/CountryPicker.ts index ccddb5920..3745df5cf 100644 --- a/packages/ui/src/utils/CountryPicker.ts +++ b/packages/ui/src/utils/CountryPicker.ts @@ -1,5 +1,6 @@ import defaultEnglishTranslation from "../FormWidgets/CountryPicker/en.json"; -import { Translation, Locales } from "../types"; + +import type { Locales, Translation } from "../types"; export const getFallbackTranslation = ( fallbackLocale: string, From 34b641d2ba7bf3876b9d0dac8ef314ec50938be1 Mon Sep 17 00:00:00 2001 From: Utsav Luintel Date: Tue, 13 Jan 2026 14:06:31 +0545 Subject: [PATCH 8/9] refactor(ui/country): add empty line and update demo --- .../CountryDisplay/CountryDisplayDemo.tsx | 48 +++++++------------ apps/demo/src/assets/css/country.css | 2 +- packages/ui/src/CountryDisplay/index.tsx | 18 +------ .../src/FormWidgets/CountryPicker/index.tsx | 21 ++------ .../{CountryPicker.ts => country-picker.ts} | 16 +++++++ 5 files changed, 40 insertions(+), 65 deletions(-) rename packages/ui/src/utils/{CountryPicker.ts => country-picker.ts} (50%) diff --git a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx index c6b2102c3..4e1200e2e 100644 --- a/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx +++ b/apps/demo/src/Views/Ui/components/CountryDisplay/CountryDisplayDemo.tsx @@ -190,43 +190,31 @@ fallbackLocale = np;
-
-

{t("countryDisplay.styles.rectangular")}

- - -
+

{t("countryDisplay.styles.rectangular")}

+ + -
-

{t("countryDisplay.styles.square")}

- - -
+

{t("countryDisplay.styles.square")}

+ + -
-

{t("countryDisplay.styles.circle")}

- - -
+

{t("countryDisplay.styles.circle")}

+ +
-
-

{t("countryDisplay.positions.left")}

- - -
+

{t("countryDisplay.positions.left")}

+ + -
-

{t("countryDisplay.positions.right")}

- - -
+

{t("countryDisplay.positions.right")}

+ + -
-

{t("countryDisplay.positions.rightEdge")}

- - -
+

{t("countryDisplay.positions.rightEdge")}

+ +
diff --git a/apps/demo/src/assets/css/country.css b/apps/demo/src/assets/css/country.css index 7e1c0f1a9..3f877a2d8 100644 --- a/apps/demo/src/assets/css/country.css +++ b/apps/demo/src/assets/css/country.css @@ -14,4 +14,4 @@ border: 1px solid #c7d2fe; color: #3730a3; width: 8rem; -} \ No newline at end of file +} diff --git a/packages/ui/src/CountryDisplay/index.tsx b/packages/ui/src/CountryDisplay/index.tsx index eace1a507..bebcb5e9b 100644 --- a/packages/ui/src/CountryDisplay/index.tsx +++ b/packages/ui/src/CountryDisplay/index.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from "react"; -import { getFallbackTranslation } from "../utils/CountryPicker"; +import { getFallbackTranslation, getFlagClass } from "../utils/country-picker"; import type { Locales } from "../types"; @@ -17,22 +17,6 @@ interface CountryDisplayProperties { renderOption?: (code: string, label: string) => React.ReactNode; } -const getFlagClass = ( - code: string | undefined, - position: string, - style: string, -) => - [ - "flag-icon", - code && `flag-icon-${code.trim().toLowerCase()}`, - position === "right" && "flag-icon-right", - position === "right-edge" && "flag-icon-right-edge", - style === "circle" && "flag-icon-rounded", - style === "square" && "flag-icon-squared", - ] - .filter(Boolean) - .join(" "); - export const Country: React.FC = ({ className = "", code, diff --git a/packages/ui/src/FormWidgets/CountryPicker/index.tsx b/packages/ui/src/FormWidgets/CountryPicker/index.tsx index 29165dca6..291ee5051 100644 --- a/packages/ui/src/FormWidgets/CountryPicker/index.tsx +++ b/packages/ui/src/FormWidgets/CountryPicker/index.tsx @@ -1,6 +1,9 @@ import React, { useCallback, useMemo } from "react"; -import { getFallbackTranslation } from "../../utils/CountryPicker"; +import { + getFallbackTranslation, + getFlagClass, +} from "../../utils/country-picker"; import { Select, ISelectProperties } from "../Select"; import defaultGroups from "./groups.json"; @@ -85,22 +88,6 @@ const getBaseOptions = ( return baseOptions; }; -const getFlagClass = ( - code: string | undefined, - position: string, - style: string, -) => - [ - "flag-icon", - code && `flag-icon-${code.trim().toLowerCase()}`, - position === "right" && "flag-icon-right", - position === "right-edge" && "flag-icon-right-edge", - style === "circle" && "flag-icon-rounded", - style === "square" && "flag-icon-squared", - ] - .filter(Boolean) - .join(" "); - const getGroups = (groups: Groups, list: Option[]): OptionGroup[] => { const optionMap = new Map( list.map((option) => [String(option.value), option]), diff --git a/packages/ui/src/utils/CountryPicker.ts b/packages/ui/src/utils/country-picker.ts similarity index 50% rename from packages/ui/src/utils/CountryPicker.ts rename to packages/ui/src/utils/country-picker.ts index 3745df5cf..3cf102ab6 100644 --- a/packages/ui/src/utils/CountryPicker.ts +++ b/packages/ui/src/utils/country-picker.ts @@ -16,3 +16,19 @@ export const getFallbackTranslation = ( return null; }; + +export const getFlagClass = ( + code: string | undefined, + position: string, + style: string, +) => + [ + "flag-icon", + code && `flag-icon-${code.trim().toLowerCase()}`, + position === "right" && "flag-icon-right", + position === "right-edge" && "flag-icon-right-edge", + style === "circle" && "flag-icon-rounded", + style === "square" && "flag-icon-squared", + ] + .filter(Boolean) + .join(" "); From 5de5d3f6d531e25872d1bff54d7a9bc89f65f451 Mon Sep 17 00:00:00 2001 From: Utsav Luintel Date: Tue, 13 Jan 2026 14:38:00 +0545 Subject: [PATCH 9/9] refactor(ui/country): update css --- packages/ui/src/assets/css/country-display.css | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/assets/css/country-display.css b/packages/ui/src/assets/css/country-display.css index af7c2ee7d..48e16689c 100644 --- a/packages/ui/src/assets/css/country-display.css +++ b/packages/ui/src/assets/css/country-display.css @@ -18,7 +18,7 @@ order: 1; } -.flag-icon { +.country .flag-icon { margin-right: 0.5rem; order: 0; flex-shrink: 0; @@ -28,15 +28,14 @@ line-height: inherit; } -.flag-icon-right { +.country .flag-icon-right { margin-right: 0; margin-left: 0.5rem; order: 2; } -.flag-icon-right-edge { +.country .flag-icon-right-edge { margin-right: 0; margin-left: auto; order: 2; } -