Class: Charming::Components::CommandPalette

Inherits:
Charming::Component show all
Defined in:
lib/charming/components/command_palette.rb

Overview

CommandPalette renders a fuzzy-searchable command picker UI. It wraps a TextInput for search input and a List for result display, dispatching key events between them. Users type to filter the registered commands by label match, navigate with up/down/home/end keys (delegated to List), confirm a selection with Enter (returns [:selected, command]), or cancel with Escape (returns :cancelled). State is serializable as a hash of value/cursor/selected_index for session persistence.

Defined Under Namespace

Classes: Command

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from View

#focused?, #layout_assigns

Constructor Details

#initialize(commands:, placeholder: "Search commands", height: nil, value: "", cursor: nil, selected_index: 0, theme: nil) ⇒ CommandPalette

Initializes the dropdown widget with a list of Command entries and search parameters for building the underlying TextInput (placeholder text, cursor position, value) and List (display height, initial selection). Returns void; the state is later serializable via state for session persistence.



21
22
23
24
25
26
27
# File 'lib/charming/components/command_palette.rb', line 21

def initialize(commands:, placeholder: "Search commands", height: nil, value: "", cursor: nil, selected_index: 0, theme: nil)
  super(theme: theme)
  @commands = commands
  @height = height
  @input = TextInput.new(value: value, placeholder: placeholder, cursor: cursor)
  @list = build_list(selected_index: selected_index)
end

Instance Attribute Details

#commandsObject (readonly)

A single command palette entry: a human-readable label and a callable or method symbol value that gets executed when the user selects it.



15
16
17
# File 'lib/charming/components/command_palette.rb', line 15

def commands
  @commands
end

#inputObject (readonly)

A single command palette entry: a human-readable label and a callable or method symbol value that gets executed when the user selects it.



15
16
17
# File 'lib/charming/components/command_palette.rb', line 15

def input
  @input
end

Instance Method Details

#handle_key(event) ⇒ Object

Handles key events by routing them to the appropriate sub-component: Escape kills the palette returning :cancelled; up/down/home/end keys go to the List selection handler via handle_list_key; all other keys (including typed characters) are passed to the TextInput which manages cursor position and input filtering. If a list key match fails, falls through to the TextInput handler. Returns nil/nil if no handler consumed the event, or :cancelled when Escape is pressed.



52
53
54
55
56
57
58
59
# File 'lib/charming/components/command_palette.rb', line 52

def handle_key(event)
  key = Charming.key_of(event)
  return :cancelled if key == :escape

  return handle_list_key(event) if list_key?(key)

  handle_input_key(event)
end

#renderObject

Renders the command palette as a vertically-stacked text representation: the search TextInput row on line 1, and then the filtered List results (or “No commands found”) on subsequent lines. Returns a multiline string suitable for terminal rendering.



64
65
66
# File 'lib/charming/components/command_palette.rb', line 64

def render
  [input.render, render_results].join("\n")
end

#selected_commandObject

Returns the currently displayed Command entry in the List at the time of calling. Returns nil if no entry is highlighted (i.e., user has opened the palette but not moved the selection). Useful for retrieving the result after key handling.



32
33
34
# File 'lib/charming/components/command_palette.rb', line 32

def selected_command
  list.selected_item
end

#stateObject

Collects the current state of the TextInput and List into a serializable hash suitable for round-trip storage in session. Returns cursor:, selected_index:.



38
39
40
41
42
43
44
# File 'lib/charming/components/command_palette.rb', line 38

def state
  {
    value: input.value,
    cursor: input.cursor,
    selected_index: list.selected_index
  }
end