Tuix.Components.Select (tuix v0.1.6)

Copy Markdown View Source

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

marker(props)

@spec marker(map()) :: String.t()

The display width of the marker prefix for the given props.

offset(selected, count, height)

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.

options(props)

@spec options(map()) :: [{String.t(), term()}]

Normalizes the :options prop to {label, value} tuples. Bare strings are their own value.

selected_index(options, value)

@spec selected_index([{String.t(), term()}], term()) :: non_neg_integer() | nil

The index of the option whose value matches, or nil.