Class: Charming::Components::TextArea

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

Overview

TextArea is a multi-line text editor component. Supports character insertion, newline insertion (plain Enter by default, plus Shift+Enter/Ctrl+J/Ctrl+N), cursor movement (left/right/up/down, home/end, page up/down), deletion (backspace/delete), and scrolling for long buffers. Vertical movement preserves a “preferred column” so left/right navigation feels stable.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from View

#focused?, #layout_assigns

Constructor Details

#initialize(value: "", placeholder: "", width: nil, height: nil, cursor: nil, offset: 0, preferred_column: nil, enter_newline: true) ⇒ TextArea

value is the initial text. placeholder is shown when the value is empty. width and height constrain the rendered output. cursor defaults to the end of the value. offset is the top-visible row. preferred_column is the column to resume at on vertical movement (defaults to the current column on first use). enter_newline (default true) makes plain Enter insert a newline — set false when a host widget wants Enter for itself (the key then falls through unhandled).



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/charming/presentation/components/text_area.rb', line 21

def initialize(value: "", placeholder: "", width: nil, height: nil, cursor: nil, offset: 0, preferred_column: nil, enter_newline: true)
  super()
  @value = value.dup
  @placeholder = placeholder
  @width = width
  @height = height
  @cursor = cursor || @value.length
  @offset = offset
  @preferred_column = preferred_column
  @enter_newline = enter_newline
  clamp_position
  ensure_cursor_visible
end

Instance Attribute Details

#cursorObject (readonly)

The current text value, cursor byte offset, top-visible row offset, and remembered column for vertical navigation, respectively.



13
14
15
# File 'lib/charming/presentation/components/text_area.rb', line 13

def cursor
  @cursor
end

#offsetObject (readonly)

The current text value, cursor byte offset, top-visible row offset, and remembered column for vertical navigation, respectively.



13
14
15
# File 'lib/charming/presentation/components/text_area.rb', line 13

def offset
  @offset
end

#preferred_columnObject (readonly)

The current text value, cursor byte offset, top-visible row offset, and remembered column for vertical navigation, respectively.



13
14
15
# File 'lib/charming/presentation/components/text_area.rb', line 13

def preferred_column
  @preferred_column
end

#valueObject (readonly)

The current text value, cursor byte offset, top-visible row offset, and remembered column for vertical navigation, respectively.



13
14
15
# File 'lib/charming/presentation/components/text_area.rb', line 13

def value
  @value
end

Instance Method Details

#captures_text?Boolean

Free-typed characters belong to this component while it is focused.

Returns:

  • (Boolean)


36
37
38
# File 'lib/charming/presentation/components/text_area.rb', line 36

def captures_text?
  true
end

#handle_key(event) ⇒ Object

Routes key events to the appropriate cursor/text mutation. Returns :handled when the event was consumed, nil otherwise.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/charming/presentation/components/text_area.rb', line 42

def handle_key(event)
  key = Charming.key_of(event)
  return :handled if newline_event?(event) && insert("\n")
  return :handled if character_event?(event) && insert(event.char)

  case key
  when :left then move_left
  when :right then move_right
  when :up then move_up
  when :down then move_down
  when :home then move_home
  when :end then move_end
  when :backspace then delete_before_cursor
  when :delete then delete_at_cursor
  when :page_up then page_up
  when :page_down then page_down
  else return nil
  end

  :handled
end

#handle_paste(event) ⇒ Object

Inserts pasted text at the cursor. Newlines are preserved; other control characters (and CRLF carriage returns) are stripped. Returns :handled.



66
67
68
69
70
# File 'lib/charming/presentation/components/text_area.rb', line 66

def handle_paste(event)
  sanitized = event.text.to_s.tr("\r", "").gsub(/[^[:print:]\n]/, "")
  insert(sanitized) unless sanitized.empty?
  :handled
end

#renderObject

Renders the visible portion of the text buffer (scrolled to ‘offset`), with each visible line either clipped to `width` or padded to it.



74
75
76
# File 'lib/charming/presentation/components/text_area.rb', line 74

def render
  visible_lines.map { |line| render_line(line) }.join("\n")
end