CountryPickerState

Owns the picker's transient UI state: sheet visibility, search query, region filter, and the pending selection.

What this class deliberately does not do

It holds no business logic and reaches no repository of the host's. It does not own the confirmed selection either — that is hoisted to the caller, which is what makes com.ezzy.ccp.countrypicker.ui.CountrySelector a controlled component. The state holder knows about the confirmed value only so it can render it and diff against it.

Pending vs. confirmed

In multi-select, pendingSelection is scratch space. confirmSelection is the only path by which it reaches the caller; dismiss and resetPendingSelection discard it. A caller's set is never mutated behind their back, so "Cancel" is genuinely a cancel rather than a visual one.

Detection precedence

applyDetection refuses to overwrite a selection the user made themselves (hasExplicitSelection). A detected country is a guess; a tapped country is a statement. Once the user has stated something, a late-arriving network lookup must not silently contradict it.

Create via rememberCountryPickerState, which also wires restoration and the recents store.

Properties

Link copied to clipboard

All countries from the data source, before any availability or region filtering.

Link copied to clipboard

Regions offered as chips, ordered by CountryRegion declaration order.

Link copied to clipboard

Whether Confirm should be enabled in multi-select.

Link copied to clipboard

The active config. Settable so a recomposition with a changed config updates behaviour without discarding the user's in-progress search or pending selection.

Link copied to clipboard

The caller's confirmed selection, mirrored here for rendering and diffing.

Link copied to clipboard

The latest detection outcome.

Link copied to clipboard

The detection source, when the current selection came from detection rather than the user.

Link copied to clipboard

A transient message for the user — currently only "you can select at most N countries".

Link copied to clipboard

True once the user has picked a country in this state's lifetime.

Link copied to clipboard

True when there is nothing to show because everything was filtered out by configuration.

Link copied to clipboard

True when a query matched nothing but countries were available to match.

Link copied to clipboard

Whether the search field currently holds focus, which drives the filled→outlined morph.

Link copied to clipboard

True when a query long enough to filter is active.

Link copied to clipboard

Whether the picker sheet is showing.

Link copied to clipboard

Load state of the country list.

Link copied to clipboard

Ranked search results over availableCountries.

Link copied to clipboard

The staged selection. In single-select this holds at most one country.

Link copied to clipboard

The countries worth one tap: the detected country, then recents, then the host's suggestions, each listed once. Disabled countries are left out — a shortcut that cannot be taken is noise.

Link copied to clipboard

Whether recent and suggested countries appear as sections at the top of the list (true), or are surfaced somewhere else — the quick-pick carousel — and left in place in the full list.

Link copied to clipboard

Recent ISO codes, most recent first, supplied by the recents store.

Link copied to clipboard

How many available countries each region holds, for the counts on the region filters.

Link copied to clipboard

Number of countries matching the current query and region.

Link copied to clipboard

The raw query the user typed. Never persisted anywhere.

Link copied to clipboard

"Did you mean …" candidates: countries within a small edit distance of the query, populated only when the query matched nothing — so a typo like "Kenia" offers Kenya instead of a dead end.

Link copied to clipboard

The sections to render, grouped and deduplicated.

Link copied to clipboard

The active region filter, or null for "All".

Functions

Link copied to clipboard

Clears the query and restores the region filter that was active before searching.

Link copied to clipboard

Promotes the pending selection to confirmed and returns it, or null when the bounds are not satisfied.

Link copied to clipboard

Dismisses the transient feedback message.

Link copied to clipboard
fun dismiss()

Dismisses the sheet, discarding any pending selection.

Link copied to clipboard
fun isDisabled(country: Country): Boolean

True when country is shown but not selectable.

Link copied to clipboard
fun isPending(country: Country): Boolean

True when country is in the pending selection.

Link copied to clipboard

Marks the selection as user-made, e.g. when the host restores a saved choice as explicit.

Link copied to clipboard

Records whether the search field holds focus.

Link copied to clipboard
fun open()

Opens the sheet, seeding the pending selection from the confirmed one.

Link copied to clipboard

Clears the pending selection. The sheet's "Reset" action.

Link copied to clipboard

Selects a region filter, or null for "All". Does not touch the selection.

Link copied to clipboard
fun toggleCountry(country: Country)

Toggles country in the pending selection.

Link copied to clipboard

Updates the query.