Lean, pre-normalized scoring representation of a picker %Item{}.
The picker's filtering hot path used to re-downcase the label, strip the icon
prefix, and rebuild the searchable text for every candidate on every keystroke.
A Candidate precomputes those fields once when the item list is set, so
scoring a large set only does the match work, not the normalization work.
A candidate carries a reference to its source item (for late display
enrichment) and a stable index reflecting the source's original ordering,
which Scorer uses to break score ties exactly as the previous brute-force
sort did.
Match positions and per-render display state deliberately do not live here; they are derived for the bounded winners only.
Summary
Functions
Builds a single candidate from an item and its index.
Builds the candidate cache for a list of items, preserving order and tagging each candidate with its original index.
Types
@type t() :: %MingaEditor.UI.Picker.Candidate{ index: non_neg_integer(), item: MingaEditor.UI.Picker.Item.t(), label_length: non_neg_integer(), norm_label: String.t(), norm_search: String.t() }
Functions
@spec from_item(MingaEditor.UI.Picker.Item.t(), non_neg_integer()) :: t()
Builds a single candidate from an item and its index.
@spec from_items([MingaEditor.UI.Picker.Item.t()]) :: [t()]
Builds the candidate cache for a list of items, preserving order and tagging each candidate with its original index.