Selkie--Widget--Select

NAME

Selkie::Widget::Select - Compact dropdown picker

SYNOPSIS

use Selkie::Widget::Select;
use Selkie::Sizing;

my $select = Selkie::Widget::Select.new(
    sizing      => Sizing.fixed(1),
    placeholder => 'Choose a model',
    max-visible => 8,
);
$select.set-items(<gpt-4 claude-opus local-model>);
$select.on-change.tap: -> UInt $idx {
    say $select.selected-value;
};

DESCRIPTION

A single-line control showing the currently selected value with a ā–¼ marker. Enter or Space opens a dropdown list as a child plane rendered on top of the surrounding layout. The dropdown opens below the control when it fits, flips above when bottom-screen space is tighter, and caps its visible rows to the terminal so long lists remain scrollable. User activation is debounced by default so duplicate terminal press events from one physical click do not open and immediately close the menu. Esc cancels; Enter commits the highlighted option.

While open, the Select acts as a local focus trap — arrow keys and Enter navigate the dropdown, not the surrounding app. Losing focus auto-closes the dropdown.

Use RadioGroup instead when you want the options always visible; use Select when you want compact real estate.

EXAMPLES

Inside a form

my $theme-select = Selkie::Widget::Select.new(
    sizing => Sizing.fixed(1),
);
$theme-select.set-items(<Auto Light Dark>);

$app.store.subscribe-with-callback(
    'sync-theme-select',
    -> $s { ($s.get-in('settings', 'theme') // 0).Int },
    -> Int $v { $theme-select.select-index($v) },
    $theme-select,
);
$theme-select.on-change.tap: -> $v {
    $app.store.dispatch('settings/set', field => 'theme', value => $v);
};

SEE ALSO

method claims-overlay-at

method claims-overlay-at(
    Int $y,
    Int $x
) returns Bool

When the dropdown is open, claim overlay rights for the dropdown rows. The framework's widget-at-in does an overlay pass against the entire tree before normal containment walk, so clicks on the dropdown reach the Select even though the parent layout's bounds end at our closed-display row. The closed-display row itself stays under standard contains-point — when the dropdown isn't open, we behave like any other 1-row widget.

method items

method items() returns List

The current option labels as a List.

method selected

method selected() returns UInt

Index of the committed selection.

method selected-value

method selected-value() returns Str

Label of the committed selection, or the Str type object when no items are set.

method is-open

method is-open() returns Bool

Whether the dropdown is currently open.

method on-change

method on-change() returns Supply

Supply that emits the new selected index whenever the selection changes (Enter / Space / mouse pick / select-index / select-by-value). Cursor-only movement inside the open dropdown does not emit until the user commits.

method set-items

method set-items(
    @new-items
) returns Mu

Replace the option labels. Preserves the current selection by label if it's still present in the new list (so a re-build of the same options doesn't snap selection back to 0); otherwise clamps to the new bounds. Closes the dropdown if it was open. Mark-dirties only — does not emit on on-change.

method select-index

method select-index(
    Int $idx where { ... }
) returns Mu

Commit the option at $idx as the new selection (clamped to the last item). Emits on on-change only when the selection actually changes (idempotent on no-ops). No-op when the list is empty.

method select-by-value

method select-by-value(
    Str:D $value
) returns Mu

Programmatically select the entry matching $value (string equality on the items list). No-op when the value isn't present or when it's already selected, so callers don't have to guard against absent items themselves. Fires on-change only when the selection actually moves.

method set-focused

method set-focused(
    Bool $f
) returns Mu

Set the input's focus state. Losing focus auto-closes any open dropdown — Select is a local focus trap while open, so leaving focus shouldn't strand the dropdown on screen.

method is-focused

method is-focused() returns Bool

Whether the widget currently has focus.

method open

method open() returns Mu

Open the dropdown. No-op when already open or when there are no items. Resets the dropdown cursor to the committed selection so the highlight starts there. Does not emit on on-change.

method close

method close() returns Mu

Close the dropdown without committing the cursor. Used by Esc and by set-focused(False); programmatic callers that want to commit should call select-index first.

method raise-active-overlay

method raise-active-overlay() returns Mu

Raise the open dropdown above later sibling/content planes. Select's dropdown intentionally escapes ordinary layout cells, so the app render loop calls this after the normal widget tree has rendered.

method destroy

method destroy() returns Mu

Tear down the dropdown plane and the widget's own plane. Called on app shutdown.

Selkie v0.10.0

High-level TUI framework built on Notcurses

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

Notcurses::Native:ver<0.4.0+>:auth<zef:apogee>

Test Dependencies

Provides

  • Selkie
  • Selkie::App
  • Selkie::App::Internal::Dispatch
  • Selkie::App::Internal::ErrorLog
  • Selkie::App::Internal::FocusTree
  • Selkie::App::Internal::HitTest
  • Selkie::App::Internal::IdleBudget
  • Selkie::App::Internal::OverlayTree
  • Selkie::App::Internal::RenderLoop
  • Selkie::App::Internal::ScreenModalLifecycle
  • Selkie::App::Internal::Terminal
  • Selkie::App::Internal::TerminalSequences
  • Selkie::Container
  • Selkie::EffectiveBounds
  • Selkie::Event
  • Selkie::Layout::Allocate
  • Selkie::Layout::HBox
  • Selkie::Layout::Split
  • Selkie::Layout::VBox
  • Selkie::Plot::Palette
  • Selkie::Plot::Scaler
  • Selkie::Plot::Ticks
  • Selkie::ScreenManager
  • Selkie::Sizing
  • Selkie::Store
  • Selkie::Style
  • Selkie::Test::Focus
  • Selkie::Test::Keys
  • Selkie::Test::Snapshot
  • Selkie::Test::Snapshot::Harness
  • Selkie::Test::Store
  • Selkie::Test::Supply
  • Selkie::Test::Tree
  • Selkie::Theme
  • Selkie::Trace
  • Selkie::Tree
  • Selkie::Widget
  • Selkie::Widget::Axis
  • Selkie::Widget::BarChart
  • Selkie::Widget::Border
  • Selkie::Widget::Button
  • Selkie::Widget::CardList
  • Selkie::Widget::Checkbox
  • Selkie::Widget::CommandPalette
  • Selkie::Widget::ConfirmModal
  • Selkie::Widget::FileBrowser
  • Selkie::Widget::FocusableByDefault
  • Selkie::Widget::Heatmap
  • Selkie::Widget::HelpOverlay
  • Selkie::Widget::Histogram
  • Selkie::Widget::Image
  • Selkie::Widget::Legend
  • Selkie::Widget::LineChart
  • Selkie::Widget::ListView
  • Selkie::Widget::Modal
  • Selkie::Widget::MultiLineInput
  • Selkie::Widget::PasswordStrength
  • Selkie::Widget::Plot
  • Selkie::Widget::ProgressBar
  • Selkie::Widget::RadioGroup
  • Selkie::Widget::RichText
  • Selkie::Widget::RichText::Span
  • Selkie::Widget::ScatterPlot
  • Selkie::Widget::ScrollView
  • Selkie::Widget::Select
  • Selkie::Widget::Sparkline
  • Selkie::Widget::Spinner
  • Selkie::Widget::TabBar
  • Selkie::Widget::Table
  • Selkie::Widget::Text
  • Selkie::Widget::TextInput
  • Selkie::Widget::TextInput::HighlightSpan
  • Selkie::Widget::TextStream
  • Selkie::Widget::Toast
  • Selkie::Widget::ViewportedCardList

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.