khateb_country_helper

pub.dev License: MIT Flutter

A Flutter package for country selection with a beautifully designed bottom sheet, multilingual support (Arabic ยท English ยท Turkish), SVG flag images from bundled assets, and a full suite of country helper utilities โ€” zero dependency on GetX or any third-party flag library.


๐Ÿ“ธ Screenshots

Light Green (Single) Light Yellow (Single) Dark Yellow (Single)
Light Green Light Yellow Dark Yellow
Dark White (Single) Multiple Selection (Light) Dark Green(single)
Dark White Multiple Light Dark Green

Features

  • ๐Ÿด SVG flag images โ€” bundled res/si/ assets, 250+ countries, rendered via jovial_svg
  • ๐Ÿ“‹ Country picker bottom sheet โ€” single & multi-select modes, shape-configurable flags (circle, rectangle, rounded), live search, dark/light auto-theming
  • ๐ŸŒ Auto-locale detection โ€” country.name reads the device locale automatically (ar / en / tr, fallback English)
  • ๐Ÿ” Country helpers โ€” look up by code, dial code, or name; scalar getters for flag, dial, max-length
  • ๐ŸŒ 200+ countries with AR / EN / TR names, ISO 3166-1 alpha-2 codes, dial codes, max phone length
  • ๐Ÿšฉ Unicode emoji fallback โ€” CountryFlagEmoji widget if you prefer emoji over SVG
  • ๐ŸŽจ Full styling control โ€” customizable badge colors, primary color, title style, search hint style, flag shape, flag size

Getting started

dependencies:
  khateb_country_helper: ^1.0.5

No extra setup required โ€” SVG assets are bundled inside the package.


Usage

1. Country picker bottom sheet

Use the unified KhatebCountryPicker class to show single or multi-select sheets.

Single Pick

import 'package:khateb_country_helper/khateb_country_helper.dart';

final Country? picked = await KhatebCountryPicker.show(
  context,
  currentCountry,                           // pre-selected Country
  flagShape: FlagShape.circle,              // circle | rectangle | rounded
  flagSize: 44,                             // you decide the size
  primaryColor: Colors.teal,
  badgeColor: Colors.grey.shade200,         // badge bg color when unselected
  badgeSelectedColor: Colors.teal.shade100, // badge bg color when selected
  title: 'ุงุฎุชุฑ ุงู„ุฏูˆู„ุฉ',
  titleStyle: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
  searchHint: 'ุงุจุญุซ...',
  searchHintStyle: const TextStyle(color: Colors.grey),
  isDark: false,                            // null = auto from Theme
);

if (picked != null) {
  print(picked.dialCode);   // +966
  print(picked.name);       // Auto-detected: ุงู„ุณุนูˆุฏูŠุฉ / Saudi Arabia / Suudi Arabistan
  print(picked.code);       // SA
}

Multi-select

final List<Country>? list = await KhatebCountryPicker.pickMultiple(
  context,
  initiallySelected: [currentCountry],      // List of pre-selected Countries
  primaryColor: Colors.indigo,
);

2. country.name โ€” auto-locale, no context needed

Country.name automatically reads the device locale via PlatformDispatcher. You never pass the locale manually:

final country = CountryHelper.getByCode('SA')!;
print(country.name);             // ุงู„ุณุนูˆุฏูŠุฉ  (on Arabic device)
print(country.name);             // Saudi Arabia  (on English device)
print(country.name);             // Suudi Arabistan  (on Turkish device)

// Explicit locale override when needed:
print(country.nameFor('ar'));    // ุงู„ุณุนูˆุฏูŠุฉ
print(country.nameFor('en'));    // Saudi Arabia
print(country.nameFor('tr'));    // Suudi Arabistan

3. SVG flag images โ€” FlagImage

// Circle (great for avatars / pickers)
FlagImage.circular(code: 'SA', size: 40)

// Rectangle
FlagImage.rectangular(code: 'SA', width: 60, height: 40)

// Rounded rectangle
FlagImage.rounded(code: 'SA', size: 40, borderRadius: 8)

4. CountryFlag โ€” flexible flag widget

// SVG image, circle shape
CountryFlag.fromCountryCode(
  'SA',
  theme: const ImageTheme(width: 40, height: 40, shape: Circle()),
)

// SVG image, rectangle
CountryFlag.fromCountryCode(
  'SA',
  theme: const ImageTheme(width: 60, height: 40, shape: Rectangle()),
)

// SVG image, rounded rectangle
CountryFlag.fromCountryCode(
  'SA',
  theme: const ImageTheme(width: 50, height: 40, shape: RoundedRectangle(8)),
)

// Plain emoji (no assets)
CountryFlag.fromCountryCode('SA', theme: const EmojiTheme(size: 32))

// From language code
CountryFlag.fromLanguageCode('ar')

// From currency code
CountryFlag.fromCurrencyCode('SAR')

// From phone prefix
CountryFlag.fromPhonePrefix('+966')

5. CountryFlagEmoji โ€” Unicode emoji flag

CountryFlagEmoji(code: 'PS')  // ๐Ÿ‡ต๐Ÿ‡ธ
CountryFlagEmoji(code: 'SA', size: 32)

// Raw emoji string (no widget)
final String? emoji = CountryFlagEmoji.emojiFromCode('JO');  // ๐Ÿ‡ฏ๐Ÿ‡ด

6. CountryHelper โ€” static utilities

// By ISO 3166-1 alpha-2 code
final Country? sa = CountryHelper.getByCode('SA');

// By dial code (with or without +)
final Country? jo = CountryHelper.getByDialCode('+962');
final Country? us = CountryHelper.getByDialCode('1');

// Scalar lookups
CountryHelper.getFlagByCode('PS');                      // ๐Ÿ‡ต๐Ÿ‡ธ
CountryHelper.getDialCodeByCode('TR');                  // +90
CountryHelper.getNameByCode('DE', locale: 'ar');        // ุฃู„ู…ุงู†ูŠุง
CountryHelper.getMaxLengthByCode('SA');                 // 13
CountryHelper.getFlagWithNameByCode('SA', locale: 'en'); // ๐Ÿ‡ธ๐Ÿ‡ฆ Saudi Arabia

// All countries (default Arab-first order)
final List<Country> all = CountryHelper.getAllCountries();

// All countries sorted alphabetically by locale
final List<Country> arabic = CountryHelper.getAllCountries(locale: 'ar');
final List<Country> english = CountryHelper.getAllCountries(locale: 'en');

7. Country model

final Country sy = CountryHelper.getByCode('SY')!;

sy.code;                    // SY
sy.flag;                    // ๐Ÿ‡ธ๐Ÿ‡พ
sy.dialCode;                // +963
sy.maxLength;               // 12
sy.name;                    // Auto-detected from device locale
sy.nameFor('ar');           // ุณูˆุฑูŠุง
sy.nameFor('en');           // Syria
sy.nameFor('tr');           // Suriye
sy.flagWithName;            // ๐Ÿ‡ธ๐Ÿ‡พ ุณูˆุฑูŠุง  (auto locale)
sy.flagWithNameFor('en');   // ๐Ÿ‡ธ๐Ÿ‡พ Syria

API Reference

KhatebCountryPicker

KhatebCountryPicker.show / pickSingle

static Future<Country?> show(
  BuildContext context,
  Country currentCountry, {
  FlagShape flagShape = FlagShape.circle,
  double flagSize = 40,
  Color? primaryColor,
  Color? badgeColor,
  Color? badgeSelectedColor,
  bool showCheckmark = true,
  bool? isDark,
  String? title,
  TextStyle? titleStyle,
  String? searchHint,
  TextStyle? searchHintStyle,
})

KhatebCountryPicker.pickMultiple

static Future<List<Country>?> pickMultiple(
  BuildContext context, {
  List<Country> initiallySelected = const [],
  FlagShape flagShape = FlagShape.circle,
  double flagSize = 40,
  Color? primaryColor,
  Color? badgeColor,
  Color? badgeSelectedColor,
  bool showCheckmark = true,
  bool? isDark,
  String? title,
  TextStyle? titleStyle,
  String? searchHint,
  TextStyle? searchHintStyle,
  String? confirmLabel,
  TextStyle? confirmStyle,
})
Parameter Type Default Description
context BuildContext required Context for the sheet
flagShape FlagShape circle circle / rectangle / rounded
flagSize double 40 Flag image width/height in dp
primaryColor Color? theme primary Accent color for selection
badgeColor Color? theme surface Dial code badge bg (unselected)
badgeSelectedColor Color? primary alpha Dial code badge bg (selected)
badgeTextColor Color? theme subtle Dial code badge text (unselected)
badgeSelectedTextColor Color? theme primary Dial code badge text (selected)
showCheckmark bool true Show trailing checkmark icon when selected
isDark bool? auto Override dark/light mode
title String? auto Sheet header text
titleStyle TextStyle? null Custom style for title
searchHint String? auto Search placeholder text
searchHintStyle TextStyle? null Custom style for search hint
confirmLabel String? auto (Multi-select) Confirm button text
confirmStyle TextStyle? null (Multi-select) Confirm text style

CountryHelper methods

Method Returns Description
getByCode(code) Country? Lookup by ISO alpha-2 code
getByDialCode(dialCode) Country? Lookup by dial code (e.g. +966)
getAllCountries({locale}) List<Country> All countries, optionally sorted
getFlagByCode(code) String Emoji flag for code
getDialCodeByCode(code) String Dial code string
getNameByCode(code, {locale}) String Localised name
getMaxLengthByCode(code) int Max phone number length
getFlagWithNameByCode(code, {locale}) String ๐Ÿ‡ธ๐Ÿ‡ฆ Saudi Arabia

FlagImage constructors

Constructor Description
FlagImage.circular(code, size) Circle-clipped SVG flag
FlagImage.rectangular(code, width, height) Rectangle SVG flag
FlagImage.rounded(code, size, {borderRadius}) Rounded rectangle SVG flag

CountryFlag factory constructors

Constructor Description
CountryFlag.fromCountryCode(code, {theme}) From ISO alpha-2 code
CountryFlag.fromLanguageCode(code, {theme}) From BCP 47 language code
CountryFlag.fromCurrencyCode(code, {theme}) From ISO 4217 currency
CountryFlag.fromPhonePrefix(prefix, {theme}) From phone prefix

Supported locales

Code Language
ar Arabic (ุงู„ุนุฑุจูŠุฉ)
en English (default fallback)
tr Turkish (Tรผrkรงe)

Any other locale falls back to English.


License

MIT ยฉ 2025 Mohammed Khateb

Libraries

country_flags
khateb_country_helper
Flutter country picker with SVG flags, single & multi-select bottom sheet, multilingual (AR/EN/TR), dial code lookup, and phone length validation.