Package-level declarations

Composables: the selectors, the phone field, the bottom sheet and its building blocks (list, rows, search field, region chips, empty/error/loading states, detection badge). All of them take their colors, shapes, dimensions, typography and motion from CountryPickerDefaults.

Types

Link copied to clipboard

A lookup from a country (or an initial letter) to its row index in the flat LazyColumn that CountryList emits.

Link copied to clipboard
data class CountryListItemScope(val match: CountryMatch, val selected: Boolean, val enabled: Boolean, val selectionMode: CountrySelectionMode, val onClick: () -> Unit)

Everything a custom row renderer needs, so listItemContent does not need a dozen parameters.

Link copied to clipboard

Interaction and validation state of a selector.

Link copied to clipboard

The visual form of a country selector. Every variant opens the same picker with the same behaviour — they differ in footprint, never in function.

Functions

Link copied to clipboard
fun CountryErrorState(onRetry: () -> Unit, modifier: Modifier = Modifier, offline: Boolean = false, style: CountryPickerStyle = CountryPickerTheme.style)

Shown when loading the country list fails.

Link copied to clipboard
fun CountryFlag(country: Country?, modifier: Modifier = Modifier, size: Dp = CountryPickerTheme.style.dimensions.flagSizeRow, style: CountryFlagStyle = CountryPickerTheme.style.layout.flagStyle, source: CountryFlagSource = CountryPickerTheme.style.layout.flagSource, flagContent: @Composable (Country) -> Unit? = null)

A country's flag.

Link copied to clipboard
fun CountryIndexRail(letters: List<Char>, onLetterSelected: (Char) -> Unit, modifier: Modifier = Modifier, style: CountryPickerStyle = CountryPickerTheme.style)

The A–Z rail down the edge of a long country list.

Link copied to clipboard
fun CountryList(state: CountryPickerState, onCountryClick: (Country) -> Unit, modifier: Modifier = Modifier, listState: LazyListState = rememberLazyListState(), contentPadding: PaddingValues = PaddingValues(bottom = LIST_BOTTOM_PADDING), leadingContent: LazyListScope.() -> Unit = {}, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, listItemContent: @Composable (CountryListItemScope) -> Unit? = null)

CountryList driven by a CountryPickerState: its sections, selection and disabled countries.

fun CountryList(sections: List<CountrySection>, selectedCountries: Set<Country>, onCountryClick: (Country) -> Unit, modifier: Modifier = Modifier, selectionMode: CountrySelectionMode = CountrySelectionMode.Single, disabledCountries: Set<String> = emptySet(), listState: LazyListState = rememberLazyListState(), contentPadding: PaddingValues = PaddingValues(bottom = LIST_BOTTOM_PADDING), leadingContent: LazyListScope.() -> Unit = {}, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, listItemContent: @Composable (CountryListItemScope) -> Unit? = null)

The country list, laid out in the style's CountryListStyle.

Link copied to clipboard
fun CountryListItem(match: CountryMatch, selected: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, selectionMode: CountrySelectionMode = CountrySelectionMode.Single, unavailable: Boolean = false, shape: Shape = CountryPickerTheme.style.shapes.row, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, trailingContent: @Composable () -> Unit? = null)

One country row.

Link copied to clipboard
fun CountryLoadingState(modifier: Modifier = Modifier, rowCount: Int = SKELETON_ROW_COUNT, style: CountryPickerStyle = CountryPickerTheme.style)

Placeholder rows shaped like the real list, with a highlight sweeping across them, while the country list loads. Announced once to screen readers as "Loading countries".

Link copied to clipboard
fun CountryNoneAvailableState(modifier: Modifier = Modifier, style: CountryPickerStyle = CountryPickerTheme.style)

Shown when the configuration allows no countries at all — almost always an integration mistake, which is why it says so plainly instead of rendering an empty list.

Link copied to clipboard
fun CountryPickerPanel(state: CountryPickerState, onCountrySelected: (Country) -> Unit, modifier: Modifier = Modifier, onSelectionConfirmed: (Set<Country>) -> Unit = {}, onClose: () -> Unit? = null, recentCountryStore: RecentCountryStore = NoOpRecentCountryStore, title: UiText = UiText.resource(Res.string.ccp_select_country), subtitle: UiText? = UiText.resource(Res.string.ccp_select_country_subtitle), style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, listItemContent: @Composable (CountryListItemScope) -> Unit? = null, emptyContent: @Composable (String) -> Unit? = null)

The complete picker — header, search, region filter, quick picks, list, every loading and empty state, and the multiple-selection bar — with no container around it.

Link copied to clipboard
fun CountryPickerSheet(state: CountryPickerState, onDismiss: () -> Unit, modifier: Modifier = Modifier, onCountrySelected: (Country) -> Unit = {}, onSelectionConfirmed: (Set<Country>) -> Unit = {}, recentCountryStore: RecentCountryStore = NoOpRecentCountryStore, title: UiText = UiText.resource(Res.string.ccp_select_country), subtitle: UiText? = UiText.resource(Res.string.ccp_select_country_subtitle), style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, listItemContent: @Composable (CountryListItemScope) -> Unit? = null, emptyContent: @Composable (String) -> Unit? = null)

The country picker, presented over the current screen.

Link copied to clipboard
fun CountryQuickPicks(picks: List<CountryQuickPick>, selectedCountries: Set<Country>, onPick: (Country) -> Unit, modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues(horizontal = CountryPickerTheme.style.dimensions.groupHorizontalMargin), style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null)

A horizontally scrolling row of one-tap shortcuts: the detected country, recent choices and the host's suggestions, as tiles above the full list.

Link copied to clipboard
fun CountryRegionFilters(selectedRegion: CountryRegion?, onRegionSelected: (CountryRegion?) -> Unit, modifier: Modifier = Modifier, regions: List<CountryRegion> = CountryRegion.entries, counts: Map<CountryRegion, Int> = emptyMap(), contentPadding: PaddingValues = PaddingValues(horizontal = CountryPickerTheme.style.dimensions.sheetHorizontalPadding), style: CountryPickerStyle = CountryPickerTheme.style)

The region filter: a recessed track holding "All" and each region, with a raised pill that slides to the selected one.

Link copied to clipboard
fun CountrySearchEmptyState(query: String, onClearSearch: () -> Unit, modifier: Modifier = Modifier, suggestions: List<Country> = emptyList(), onSuggestionClick: (Country) -> Unit = {}, style: CountryPickerStyle = CountryPickerTheme.style)

Shown when a search matches nothing.

Link copied to clipboard
fun CountrySearchField(query: String, onQueryChange: (String) -> Unit, modifier: Modifier = Modifier, placeholder: UiText = UiText.resource(Res.string.ccp_search_hint), onFocusChanged: (Boolean) -> Unit = {}, onSearchAction: () -> Unit = {}, onCancel: () -> Unit? = null, autoFocus: Boolean = false, style: CountryPickerStyle = CountryPickerTheme.style)

The search field at the top of the picker.

Link copied to clipboard
fun CountrySectionHeader(section: CountrySection, modifier: Modifier = Modifier, showCount: Boolean = false, isFirst: Boolean = false, style: CountryPickerStyle = CountryPickerTheme.style)

A section's title, in small capitals above its group.

Link copied to clipboard
fun CountrySelector(selectedCountry: Country?, onCountrySelected: (Country) -> Unit, modifier: Modifier = Modifier, config: CountryPickerConfig = CountryPickerDefaults.config(), variant: CountrySelectorVariant = CountrySelectorVariant.Elevated, enabled: Boolean = true, state: CountrySelectorState = CountrySelectorState.Default, label: UiText? = UiText.resource(Res.string.ccp_country_of_residence), placeholder: UiText? = UiText.resource(Res.string.ccp_select_country_placeholder), labelMode: InputLabelMode = InputLabelMode.Floating, supportingContent: CountrySupportingContent = CountrySupportingContent.None, supportingText: UiText? = null, errorText: UiText? = null, successText: UiText? = null, required: Boolean = false, sheetTitle: UiText = UiText.resource(Res.string.ccp_select_country), sheetSubtitle: UiText? = UiText.resource(Res.string.ccp_select_country_subtitle), recentCountryStore: RecentCountryStore = NoOpRecentCountryStore, detector: CountryDetector? = null, detectionBehavior: CountryDetectionBehavior = CountryDetectionBehavior.ShowBadge, repository: CountryRepository = CountryRepository.Default, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, trailingContent: @Composable () -> Unit? = null, selectorContent: @Composable RowScope.(Country?) -> Unit? = null, listItemContent: @Composable (CountryListItemScope) -> Unit? = null, emptyContent: @Composable (String) -> Unit? = null)

A country field that opens the picker.

Link copied to clipboard
fun CountrySelectorField(country: Country?, onClick: () -> Unit, modifier: Modifier = Modifier, isOpen: Boolean = false, state: CountrySelectorState = CountrySelectorState.Default, variant: CountrySelectorVariant = CountrySelectorVariant.Elevated, label: UiText? = null, placeholder: UiText? = null, labelMode: InputLabelMode = InputLabelMode.Floating, supportingContent: CountrySupportingContent = CountrySupportingContent.None, required: Boolean = false, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, trailingContent: @Composable () -> Unit? = null, selectorContent: @Composable RowScope.(Country?) -> Unit? = null, accessibilityDescription: String? = null)

The selector field alone, without the picker — for a host that already manages when its picker is shown.

Link copied to clipboard
fun DetectedCountryBadge(source: CountryDetectionSource, modifier: Modifier = Modifier, style: CountryPickerStyle = CountryPickerTheme.style)

"📍 Detected · From your SIM card · tap to change" — shown under a field whose value came from detection rather than from the user.

Link copied to clipboard
fun DetectedCountrySuggestion(country: Country, source: CountryDetectionSource, onAccept: () -> Unit, modifier: Modifier = Modifier, visible: Boolean = true, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null)

A banner offering the detected country — "Looks like you're in Kenya, from your SIM card." — with a one-tap Use action, for when detection should suggest rather than decide.

Link copied to clipboard
fun MultiCountryPickerSheet(state: CountryPickerState, onSelectionConfirmed: (Set<Country>) -> Unit, onDismiss: () -> Unit, modifier: Modifier = Modifier, recentCountryStore: RecentCountryStore = NoOpRecentCountryStore, title: UiText = UiText.resource(Res.string.ccp_select_country), subtitle: UiText? = UiText.resource(Res.string.ccp_select_country_subtitle), style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, listItemContent: @Composable (CountryListItemScope) -> Unit? = null)

CountryPickerSheet for multiple selection, so a call site cannot pass the wrong callback.

Link copied to clipboard
fun MultiCountrySelector(selectedCountries: Set<Country>, onSelectionConfirmed: (Set<Country>) -> Unit, modifier: Modifier = Modifier, config: CountryPickerConfig = CountryPickerDefaults.multiSelectConfig(), variant: CountrySelectorVariant = CountrySelectorVariant.Elevated, enabled: Boolean = true, state: CountrySelectorState = CountrySelectorState.Default, label: UiText? = UiText.resource(Res.string.ccp_country_of_residence), placeholder: UiText? = UiText.resource(Res.string.ccp_select_country_placeholder), summaryText: UiText? = null, showChips: Boolean = true, supportingText: UiText? = null, errorText: UiText? = null, required: Boolean = false, sheetTitle: UiText = UiText.resource(Res.string.ccp_select_country), sheetSubtitle: UiText? = UiText.resource(Res.string.ccp_select_country_subtitle), recentCountryStore: RecentCountryStore = NoOpRecentCountryStore, repository: CountryRepository = CountryRepository.Default, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, listItemContent: @Composable (CountryListItemScope) -> Unit? = null)

A field for choosing several countries.

Link copied to clipboard
fun PhoneCountryCodeSelector(selectedCountry: Country, onCountrySelected: (Country) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, config: CountryPickerConfig = CountryPickerDefaults.phoneConfig(), sheetTitle: UiText = UiText.resource(Res.string.ccp_country_code_title), sheetSubtitle: UiText? = UiText.resource(Res.string.ccp_country_code_subtitle), recentCountryStore: RecentCountryStore = NoOpRecentCountryStore, repository: CountryRepository = CountryRepository.Default, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null)

A standalone dial-code pill — 🇰🇪 +254 ˅ — that opens the country-code picker.

Link copied to clipboard
fun PhoneNumberField(onValueChange: (PhoneNumberValue) -> Unit, modifier: Modifier = Modifier, state: PhoneNumberFieldState = rememberPhoneNumberFieldState( initialCountry = DefaultCountryDataSource.defaultInitialCountry(compositionLocale()), ), enabled: Boolean = true, readOnly: Boolean = false, variant: CountrySelectorVariant = CountrySelectorVariant.Elevated, label: UiText? = UiText.resource(Res.string.ccp_phone_number), accessibilityLabel: UiText? = label, placeholder: UiText? = null, inputStyle: PhoneNumberInputStyle = PhoneNumberInputDefaults.style(), config: CountryPickerConfig = CountryPickerDefaults.phoneConfig(), showHelperText: Boolean = true, showClearButton: Boolean = true, autofillEnabled: Boolean = true, isError: Boolean = false, errorMessage: UiText? = null, validateWhileTyping: Boolean = false, verificationController: PhoneVerificationController? = null, recentCountryStore: RecentCountryStore = NoOpRecentCountryStore, repository: CountryRepository = CountryRepository.Default, style: CountryPickerStyle = CountryPickerTheme.style, flagContent: @Composable (Country) -> Unit? = null, onDone: () -> Unit = {})

An international phone number field: the country prefix and the number in one field.

Link copied to clipboard

Builds the CountryListIndex for sections, recomputed only when the sections change.