The behaviour implementation and pure helpers behind
Tuix.Components.select/1, a vertical list picker.
Selects are controlled and stateless: the selection follows the highlight,
so :up / :down / :home / :end emit %Tuix.Event.Select{} with the
new value immediately, and the highlighted row is simply the option
matching props.value — owned by the app. Navigation is clamped (no
wrap-around); boundary presses and empty option lists are consumed.
Everything else (:enter, :space, ctrl combos) falls through to the
app with target set, so commit-on-Enter flows are one
%Key{key: :enter, target: id} clause away.
Summary
Functions
The display width of the marker prefix for the given props.
The scroll offset (in rows) that keeps the selected row visible in
height rows: max(0, selected - height + 1), clamped so the window
never extends past the last option. Pure — like an input's horizontal
scroll, no stored state.
Normalizes the :options prop to {label, value} tuples. Bare strings
are their own value.
The index of the option whose value matches, or nil.
Functions
The display width of the marker prefix for the given props.
@spec offset(non_neg_integer() | nil, non_neg_integer(), non_neg_integer()) :: non_neg_integer()
The scroll offset (in rows) that keeps the selected row visible in
height rows: max(0, selected - height + 1), clamped so the window
never extends past the last option. Pure — like an input's horizontal
scroll, no stored state.
Normalizes the :options prop to {label, value} tuples. Bare strings
are their own value.
@spec selected_index([{String.t(), term()}], term()) :: non_neg_integer() | nil
The index of the option whose value matches, or nil.