ratatui_ruby 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +1 -1
  3. data/.builds/ruby-3.3.yml +1 -1
  4. data/.builds/ruby-3.4.yml +1 -1
  5. data/.builds/ruby-4.0.0.yml +1 -1
  6. data/AGENTS.md +2 -1
  7. data/CHANGELOG.md +98 -0
  8. data/REUSE.toml +5 -0
  9. data/Rakefile +1 -1
  10. data/Steepfile +49 -0
  11. data/doc/concepts/debugging.md +401 -0
  12. data/doc/getting_started/quickstart.md +8 -3
  13. data/doc/images/app_all_events.png +0 -0
  14. data/doc/images/app_color_picker.png +0 -0
  15. data/doc/images/app_debugging_showcase.gif +0 -0
  16. data/doc/images/app_debugging_showcase.png +0 -0
  17. data/doc/images/app_login_form.png +0 -0
  18. data/doc/images/app_stateful_interaction.png +0 -0
  19. data/doc/images/verify_quickstart_dsl.png +0 -0
  20. data/doc/images/verify_quickstart_layout.png +0 -0
  21. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  22. data/doc/images/verify_readme_usage.png +0 -0
  23. data/doc/images/widget_barchart.png +0 -0
  24. data/doc/images/widget_block.png +0 -0
  25. data/doc/images/widget_box.png +0 -0
  26. data/doc/images/widget_calendar.png +0 -0
  27. data/doc/images/widget_canvas.png +0 -0
  28. data/doc/images/widget_cell.png +0 -0
  29. data/doc/images/widget_center.png +0 -0
  30. data/doc/images/widget_chart.png +0 -0
  31. data/doc/images/widget_gauge.png +0 -0
  32. data/doc/images/widget_layout_split.png +0 -0
  33. data/doc/images/widget_line_gauge.png +0 -0
  34. data/doc/images/widget_list.png +0 -0
  35. data/doc/images/widget_map.png +0 -0
  36. data/doc/images/widget_overlay.png +0 -0
  37. data/doc/images/widget_popup.png +0 -0
  38. data/doc/images/widget_ratatui_logo.png +0 -0
  39. data/doc/images/widget_ratatui_mascot.png +0 -0
  40. data/doc/images/widget_rect.png +0 -0
  41. data/doc/images/widget_render.png +0 -0
  42. data/doc/images/widget_rich_text.png +0 -0
  43. data/doc/images/widget_scroll_text.png +0 -0
  44. data/doc/images/widget_scrollbar.png +0 -0
  45. data/doc/images/widget_sparkline.png +0 -0
  46. data/doc/images/widget_style_colors.png +0 -0
  47. data/doc/images/widget_table.png +0 -0
  48. data/doc/images/widget_tabs.png +0 -0
  49. data/doc/images/widget_text_width.png +0 -0
  50. data/doc/troubleshooting/async.md +4 -0
  51. data/examples/app_debugging_showcase/README.md +119 -0
  52. data/examples/app_debugging_showcase/app.rb +318 -0
  53. data/examples/widget_canvas/app.rb +19 -14
  54. data/examples/widget_gauge/app.rb +18 -3
  55. data/examples/widget_layout_split/app.rb +10 -4
  56. data/examples/widget_list/app.rb +22 -6
  57. data/examples/widget_rect/app.rb +7 -6
  58. data/examples/widget_rich_text/app.rb +62 -37
  59. data/examples/widget_style_colors/app.rb +26 -47
  60. data/examples/widget_table/app.rb +28 -5
  61. data/examples/widget_text_width/app.rb +6 -4
  62. data/ext/ratatui_ruby/Cargo.lock +48 -1
  63. data/ext/ratatui_ruby/Cargo.toml +6 -2
  64. data/ext/ratatui_ruby/src/color.rs +82 -0
  65. data/ext/ratatui_ruby/src/errors.rs +28 -0
  66. data/ext/ratatui_ruby/src/events.rs +15 -14
  67. data/ext/ratatui_ruby/src/lib.rs +56 -0
  68. data/ext/ratatui_ruby/src/rendering.rs +3 -1
  69. data/ext/ratatui_ruby/src/style.rs +48 -21
  70. data/ext/ratatui_ruby/src/terminal.rs +40 -9
  71. data/ext/ratatui_ruby/src/text.rs +21 -9
  72. data/ext/ratatui_ruby/src/widgets/chart.rs +2 -1
  73. data/ext/ratatui_ruby/src/widgets/layout.rs +90 -2
  74. data/ext/ratatui_ruby/src/widgets/list.rs +6 -5
  75. data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
  76. data/ext/ratatui_ruby/src/widgets/table.rs +7 -6
  77. data/ext/ratatui_ruby/src/widgets/table_state.rs +55 -0
  78. data/ext/ratatui_ruby/src/widgets/tabs.rs +3 -2
  79. data/lib/ratatui_ruby/buffer/cell.rb +25 -15
  80. data/lib/ratatui_ruby/buffer.rb +134 -2
  81. data/lib/ratatui_ruby/cell.rb +13 -5
  82. data/lib/ratatui_ruby/debug.rb +215 -0
  83. data/lib/ratatui_ruby/event/key.rb +3 -2
  84. data/lib/ratatui_ruby/event.rb +1 -1
  85. data/lib/ratatui_ruby/layout/constraint.rb +49 -0
  86. data/lib/ratatui_ruby/layout/layout.rb +119 -13
  87. data/lib/ratatui_ruby/layout/position.rb +55 -0
  88. data/lib/ratatui_ruby/layout/rect.rb +188 -0
  89. data/lib/ratatui_ruby/layout/size.rb +55 -0
  90. data/lib/ratatui_ruby/layout.rb +4 -0
  91. data/lib/ratatui_ruby/style/color.rb +149 -0
  92. data/lib/ratatui_ruby/style/style.rb +51 -4
  93. data/lib/ratatui_ruby/style.rb +2 -0
  94. data/lib/ratatui_ruby/symbols.rb +435 -0
  95. data/lib/ratatui_ruby/synthetic_events.rb +1 -1
  96. data/lib/ratatui_ruby/table_state.rb +51 -0
  97. data/lib/ratatui_ruby/terminal_lifecycle.rb +2 -1
  98. data/lib/ratatui_ruby/test_helper/event_injection.rb +6 -1
  99. data/lib/ratatui_ruby/test_helper.rb +9 -0
  100. data/lib/ratatui_ruby/text/line.rb +245 -0
  101. data/lib/ratatui_ruby/text/span.rb +158 -0
  102. data/lib/ratatui_ruby/text.rb +99 -0
  103. data/lib/ratatui_ruby/tui/canvas_factories.rb +103 -0
  104. data/lib/ratatui_ruby/tui/core.rb +13 -2
  105. data/lib/ratatui_ruby/tui/layout_factories.rb +50 -3
  106. data/lib/ratatui_ruby/tui/state_factories.rb +42 -0
  107. data/lib/ratatui_ruby/tui/text_factories.rb +40 -0
  108. data/lib/ratatui_ruby/tui/widget_factories.rb +135 -60
  109. data/lib/ratatui_ruby/tui.rb +22 -1
  110. data/lib/ratatui_ruby/version.rb +1 -1
  111. data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -0
  112. data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -0
  113. data/lib/ratatui_ruby/widgets/bar_chart.rb +30 -20
  114. data/lib/ratatui_ruby/widgets/block.rb +14 -6
  115. data/lib/ratatui_ruby/widgets/calendar.rb +2 -0
  116. data/lib/ratatui_ruby/widgets/canvas.rb +56 -0
  117. data/lib/ratatui_ruby/widgets/cell.rb +2 -0
  118. data/lib/ratatui_ruby/widgets/center.rb +2 -0
  119. data/lib/ratatui_ruby/widgets/chart.rb +6 -0
  120. data/lib/ratatui_ruby/widgets/clear.rb +2 -0
  121. data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
  122. data/lib/ratatui_ruby/widgets/cursor.rb +2 -0
  123. data/lib/ratatui_ruby/widgets/gauge.rb +61 -3
  124. data/lib/ratatui_ruby/widgets/line_gauge.rb +66 -4
  125. data/lib/ratatui_ruby/widgets/list.rb +87 -3
  126. data/lib/ratatui_ruby/widgets/list_item.rb +2 -0
  127. data/lib/ratatui_ruby/widgets/overlay.rb +2 -0
  128. data/lib/ratatui_ruby/widgets/paragraph.rb +4 -0
  129. data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -0
  130. data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -0
  131. data/lib/ratatui_ruby/widgets/row.rb +45 -0
  132. data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -0
  133. data/lib/ratatui_ruby/widgets/shape/label.rb +2 -0
  134. data/lib/ratatui_ruby/widgets/sparkline.rb +21 -13
  135. data/lib/ratatui_ruby/widgets/table.rb +13 -3
  136. data/lib/ratatui_ruby/widgets/tabs.rb +6 -4
  137. data/lib/ratatui_ruby/widgets.rb +1 -0
  138. data/lib/ratatui_ruby.rb +40 -9
  139. data/sig/examples/app_all_events/model/app_model.rbs +23 -0
  140. data/sig/examples/app_all_events/model/event_entry.rbs +15 -8
  141. data/sig/examples/app_all_events/model/timestamp.rbs +1 -1
  142. data/sig/examples/app_all_events/view.rbs +1 -1
  143. data/sig/examples/app_stateful_interaction/app.rbs +5 -5
  144. data/sig/examples/widget_block_demo/app.rbs +6 -6
  145. data/sig/manifest.yaml +5 -0
  146. data/sig/patches/data.rbs +26 -0
  147. data/sig/patches/debugger__.rbs +8 -0
  148. data/sig/ratatui_ruby/buffer/cell.rbs +46 -0
  149. data/sig/ratatui_ruby/buffer.rbs +18 -0
  150. data/sig/ratatui_ruby/cell.rbs +44 -0
  151. data/sig/ratatui_ruby/clear.rbs +18 -0
  152. data/sig/ratatui_ruby/constraint.rbs +26 -0
  153. data/sig/ratatui_ruby/debug.rbs +45 -0
  154. data/sig/ratatui_ruby/draw.rbs +30 -0
  155. data/sig/ratatui_ruby/event.rbs +68 -8
  156. data/sig/ratatui_ruby/frame.rbs +4 -4
  157. data/sig/ratatui_ruby/interfaces.rbs +25 -0
  158. data/sig/ratatui_ruby/layout/constraint.rbs +39 -0
  159. data/sig/ratatui_ruby/layout/layout.rbs +45 -0
  160. data/sig/ratatui_ruby/layout/position.rbs +18 -0
  161. data/sig/ratatui_ruby/layout/rect.rbs +64 -0
  162. data/sig/ratatui_ruby/layout/size.rbs +18 -0
  163. data/sig/ratatui_ruby/output_guard.rbs +23 -0
  164. data/sig/ratatui_ruby/ratatui_ruby.rbs +83 -4
  165. data/sig/ratatui_ruby/rect.rbs +17 -0
  166. data/sig/ratatui_ruby/style/color.rbs +22 -0
  167. data/sig/ratatui_ruby/style/style.rbs +29 -0
  168. data/sig/ratatui_ruby/symbols.rbs +141 -0
  169. data/sig/ratatui_ruby/synthetic_events.rbs +21 -0
  170. data/sig/ratatui_ruby/table_state.rbs +6 -0
  171. data/sig/ratatui_ruby/terminal_lifecycle.rbs +31 -0
  172. data/sig/ratatui_ruby/test_helper/event_injection.rbs +2 -2
  173. data/sig/ratatui_ruby/test_helper/snapshot.rbs +22 -3
  174. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +8 -1
  175. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -3
  176. data/sig/ratatui_ruby/text/line.rbs +27 -0
  177. data/sig/ratatui_ruby/text/span.rbs +23 -0
  178. data/sig/ratatui_ruby/text.rbs +12 -0
  179. data/sig/ratatui_ruby/tui/buffer_factories.rbs +1 -1
  180. data/sig/ratatui_ruby/tui/canvas_factories.rbs +23 -5
  181. data/sig/ratatui_ruby/tui/core.rbs +2 -2
  182. data/sig/ratatui_ruby/tui/layout_factories.rbs +16 -2
  183. data/sig/ratatui_ruby/tui/state_factories.rbs +8 -3
  184. data/sig/ratatui_ruby/tui/style_factories.rbs +3 -1
  185. data/sig/ratatui_ruby/tui/text_factories.rbs +7 -4
  186. data/sig/ratatui_ruby/tui/widget_factories.rbs +123 -30
  187. data/sig/ratatui_ruby/widgets/bar_chart.rbs +95 -0
  188. data/sig/ratatui_ruby/widgets/block.rbs +51 -0
  189. data/sig/ratatui_ruby/widgets/calendar.rbs +45 -0
  190. data/sig/ratatui_ruby/widgets/canvas.rbs +95 -0
  191. data/sig/ratatui_ruby/widgets/chart.rbs +91 -0
  192. data/sig/ratatui_ruby/widgets/coerceable_widget.rbs +26 -0
  193. data/sig/ratatui_ruby/widgets/gauge.rbs +44 -0
  194. data/sig/ratatui_ruby/widgets/line_gauge.rbs +48 -0
  195. data/sig/ratatui_ruby/widgets/list.rbs +63 -0
  196. data/sig/ratatui_ruby/widgets/misc.rbs +158 -0
  197. data/sig/ratatui_ruby/widgets/paragraph.rbs +45 -0
  198. data/sig/ratatui_ruby/widgets/row.rbs +43 -0
  199. data/sig/ratatui_ruby/widgets/scrollbar.rbs +53 -0
  200. data/sig/ratatui_ruby/widgets/shape/label.rbs +37 -0
  201. data/sig/ratatui_ruby/widgets/sparkline.rbs +45 -0
  202. data/sig/ratatui_ruby/widgets/table.rbs +78 -0
  203. data/sig/ratatui_ruby/widgets/tabs.rbs +44 -0
  204. data/sig/ratatui_ruby/{schema/list_item.rbs → widgets.rbs} +4 -4
  205. data/tasks/steep.rake +11 -0
  206. metadata +80 -63
  207. data/doc/contributors/v1.0.0_blockers.md +0 -870
  208. data/doc/troubleshooting/debugging.md +0 -101
  209. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +0 -47
  210. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +0 -25
  211. data/lib/ratatui_ruby/schema/bar_chart.rb +0 -287
  212. data/lib/ratatui_ruby/schema/block.rb +0 -198
  213. data/lib/ratatui_ruby/schema/calendar.rb +0 -84
  214. data/lib/ratatui_ruby/schema/canvas.rb +0 -239
  215. data/lib/ratatui_ruby/schema/center.rb +0 -67
  216. data/lib/ratatui_ruby/schema/chart.rb +0 -159
  217. data/lib/ratatui_ruby/schema/clear.rb +0 -62
  218. data/lib/ratatui_ruby/schema/constraint.rb +0 -151
  219. data/lib/ratatui_ruby/schema/cursor.rb +0 -50
  220. data/lib/ratatui_ruby/schema/gauge.rb +0 -72
  221. data/lib/ratatui_ruby/schema/layout.rb +0 -122
  222. data/lib/ratatui_ruby/schema/line_gauge.rb +0 -80
  223. data/lib/ratatui_ruby/schema/list.rb +0 -135
  224. data/lib/ratatui_ruby/schema/list_item.rb +0 -51
  225. data/lib/ratatui_ruby/schema/overlay.rb +0 -51
  226. data/lib/ratatui_ruby/schema/paragraph.rb +0 -107
  227. data/lib/ratatui_ruby/schema/ratatui_logo.rb +0 -31
  228. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +0 -36
  229. data/lib/ratatui_ruby/schema/rect.rb +0 -174
  230. data/lib/ratatui_ruby/schema/row.rb +0 -76
  231. data/lib/ratatui_ruby/schema/scrollbar.rb +0 -143
  232. data/lib/ratatui_ruby/schema/shape/label.rb +0 -76
  233. data/lib/ratatui_ruby/schema/sparkline.rb +0 -142
  234. data/lib/ratatui_ruby/schema/style.rb +0 -97
  235. data/lib/ratatui_ruby/schema/table.rb +0 -141
  236. data/lib/ratatui_ruby/schema/tabs.rb +0 -85
  237. data/lib/ratatui_ruby/schema/text.rb +0 -217
  238. data/sig/examples/app_all_events/model/events.rbs +0 -15
  239. data/sig/examples/app_all_events/view_state.rbs +0 -21
  240. data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +0 -22
  241. data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +0 -19
  242. data/sig/ratatui_ruby/schema/bar_chart.rbs +0 -38
  243. data/sig/ratatui_ruby/schema/block.rbs +0 -18
  244. data/sig/ratatui_ruby/schema/calendar.rbs +0 -23
  245. data/sig/ratatui_ruby/schema/canvas.rbs +0 -81
  246. data/sig/ratatui_ruby/schema/center.rbs +0 -17
  247. data/sig/ratatui_ruby/schema/chart.rbs +0 -39
  248. data/sig/ratatui_ruby/schema/constraint.rbs +0 -30
  249. data/sig/ratatui_ruby/schema/cursor.rbs +0 -16
  250. data/sig/ratatui_ruby/schema/draw.rbs +0 -33
  251. data/sig/ratatui_ruby/schema/gauge.rbs +0 -23
  252. data/sig/ratatui_ruby/schema/layout.rbs +0 -27
  253. data/sig/ratatui_ruby/schema/line_gauge.rbs +0 -24
  254. data/sig/ratatui_ruby/schema/list.rbs +0 -28
  255. data/sig/ratatui_ruby/schema/overlay.rbs +0 -15
  256. data/sig/ratatui_ruby/schema/paragraph.rbs +0 -20
  257. data/sig/ratatui_ruby/schema/ratatui_logo.rbs +0 -14
  258. data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +0 -17
  259. data/sig/ratatui_ruby/schema/rect.rbs +0 -48
  260. data/sig/ratatui_ruby/schema/row.rbs +0 -28
  261. data/sig/ratatui_ruby/schema/scrollbar.rbs +0 -42
  262. data/sig/ratatui_ruby/schema/sparkline.rbs +0 -22
  263. data/sig/ratatui_ruby/schema/style.rbs +0 -19
  264. data/sig/ratatui_ruby/schema/table.rbs +0 -32
  265. data/sig/ratatui_ruby/schema/tabs.rbs +0 -21
  266. data/sig/ratatui_ruby/schema/text.rbs +0 -31
  267. /data/lib/ratatui_ruby/{schema/draw.rb → draw.rb} +0 -0
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ module Symbols
10
+ module Shade
11
+ EMPTY: String
12
+ LIGHT: String
13
+ MEDIUM: String
14
+ DARK: String
15
+ FULL: String
16
+ end
17
+
18
+ # Type alias for line set hashes
19
+ type line_set = {
20
+ vertical: String,
21
+ horizontal: String,
22
+ top_right: String,
23
+ top_left: String,
24
+ bottom_right: String,
25
+ bottom_left: String,
26
+ vertical_left: String,
27
+ vertical_right: String,
28
+ horizontal_down: String,
29
+ horizontal_up: String,
30
+ cross: String
31
+ }
32
+
33
+ module Line
34
+ # Individual character constants
35
+ VERTICAL: String
36
+ DOUBLE_VERTICAL: String
37
+ THICK_VERTICAL: String
38
+ HORIZONTAL: String
39
+ DOUBLE_HORIZONTAL: String
40
+ THICK_HORIZONTAL: String
41
+ TOP_RIGHT: String
42
+ ROUNDED_TOP_RIGHT: String
43
+ DOUBLE_TOP_RIGHT: String
44
+ THICK_TOP_RIGHT: String
45
+ TOP_LEFT: String
46
+ ROUNDED_TOP_LEFT: String
47
+ DOUBLE_TOP_LEFT: String
48
+ THICK_TOP_LEFT: String
49
+ BOTTOM_RIGHT: String
50
+ ROUNDED_BOTTOM_RIGHT: String
51
+ DOUBLE_BOTTOM_RIGHT: String
52
+ THICK_BOTTOM_RIGHT: String
53
+ BOTTOM_LEFT: String
54
+ ROUNDED_BOTTOM_LEFT: String
55
+ DOUBLE_BOTTOM_LEFT: String
56
+ THICK_BOTTOM_LEFT: String
57
+ VERTICAL_LEFT: String
58
+ DOUBLE_VERTICAL_LEFT: String
59
+ THICK_VERTICAL_LEFT: String
60
+ VERTICAL_RIGHT: String
61
+ DOUBLE_VERTICAL_RIGHT: String
62
+ THICK_VERTICAL_RIGHT: String
63
+ HORIZONTAL_DOWN: String
64
+ DOUBLE_HORIZONTAL_DOWN: String
65
+ THICK_HORIZONTAL_DOWN: String
66
+ HORIZONTAL_UP: String
67
+ DOUBLE_HORIZONTAL_UP: String
68
+ THICK_HORIZONTAL_UP: String
69
+ CROSS: String
70
+ DOUBLE_CROSS: String
71
+ THICK_CROSS: String
72
+
73
+ # Predefined sets
74
+ NORMAL: line_set
75
+ ROUNDED: line_set
76
+ DOUBLE: line_set
77
+ THICK: line_set
78
+ end
79
+
80
+ # Type alias for bar set hashes
81
+ type bar_set = {
82
+ full: String,
83
+ seven_eighths: String,
84
+ three_quarters: String,
85
+ five_eighths: String,
86
+ half: String,
87
+ three_eighths: String,
88
+ one_quarter: String,
89
+ one_eighth: String,
90
+ empty: String
91
+ }
92
+
93
+ module Bar
94
+ # Individual character constants
95
+ FULL: String
96
+ SEVEN_EIGHTHS: String
97
+ THREE_QUARTERS: String
98
+ FIVE_EIGHTHS: String
99
+ HALF: String
100
+ THREE_EIGHTHS: String
101
+ ONE_QUARTER: String
102
+ ONE_EIGHTH: String
103
+
104
+ # Predefined sets
105
+ NINE_LEVELS: bar_set
106
+ THREE_LEVELS: bar_set
107
+ end
108
+
109
+ module Block
110
+ # Individual character constants
111
+ FULL: String
112
+ SEVEN_EIGHTHS: String
113
+ THREE_QUARTERS: String
114
+ FIVE_EIGHTHS: String
115
+ HALF: String
116
+ THREE_EIGHTHS: String
117
+ ONE_QUARTER: String
118
+ ONE_EIGHTH: String
119
+
120
+ # Predefined sets (same structure as bar_set)
121
+ NINE_LEVELS: bar_set
122
+ THREE_LEVELS: bar_set
123
+ end
124
+
125
+ # Type alias for scrollbar set hashes
126
+ type scrollbar_set = {
127
+ track: String,
128
+ thumb: String,
129
+ begin_char: String,
130
+ end_char: String
131
+ }
132
+
133
+ module Scrollbar
134
+ # Predefined sets
135
+ DOUBLE_VERTICAL: scrollbar_set
136
+ DOUBLE_HORIZONTAL: scrollbar_set
137
+ VERTICAL: scrollbar_set
138
+ HORIZONTAL: scrollbar_set
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ # SPDX-License-Identifier: AGPL-3.0-or-later
9
+
10
+ module RatatuiRuby
11
+ # Synthetic event queue for injecting events into the event loop.
12
+ # Used primarily for testing and the andThen-like integration pattern.
13
+ module SyntheticEvents
14
+ @queue: Array[Event]
15
+
16
+ def self.push: (Event event) -> void
17
+ def self.pop: () -> Event?
18
+ def self.clear: () -> void
19
+ def self.pending?: () -> bool
20
+ end
21
+ end
@@ -10,10 +10,16 @@
10
10
  module RatatuiRuby
11
11
  class TableState
12
12
  def self.new: (?Integer? selected) -> TableState
13
+ def self.with_selected_cell: ([Integer, Integer]? cell) -> TableState
13
14
  def select: (Integer? index) -> nil
14
15
  def selected: () -> Integer?
15
16
  def select_column: (Integer? index) -> nil
16
17
  def selected_column: () -> Integer?
18
+ def selected_cell: () -> [Integer, Integer]?
19
+ def select_next_column: () -> nil
20
+ def select_previous_column: () -> nil
21
+ def select_first_column: () -> nil
22
+ def select_last_column: () -> nil
17
23
  def offset: () -> Integer
18
24
  def scroll_down_by: (Integer n) -> nil
19
25
  def scroll_up_by: (Integer n) -> nil
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ # SPDX-License-Identifier: AGPL-3.0-or-later
9
+
10
+ module RatatuiRuby
11
+ # Terminal lifecycle management for TUI sessions.
12
+ # Provides methods to initialize and restore the terminal state.
13
+ module TerminalLifecycle
14
+ @tui_session_active: bool?
15
+ @headless_mode: bool?
16
+
17
+ def init_terminal: (?focus_events: bool, ?bracketed_paste: bool) -> void
18
+ def restore_terminal: () -> void
19
+ def terminal_active?: () -> (bool | nil)
20
+ def init_test_terminal: (Integer width, Integer height) -> void
21
+ def run: (?focus_events: bool, ?bracketed_paste: bool) { (TUI) -> void } -> void
22
+
23
+ # Private native methods
24
+ def _init_terminal: (bool focus_events, bool bracketed_paste) -> void
25
+ def _init_test_terminal: (Integer width, Integer height) -> void
26
+ def _restore_terminal: () -> void
27
+ def flush_warnings: () -> void
28
+ def flush_panic_info: () -> void
29
+ end
30
+ end
31
+
@@ -10,12 +10,12 @@
10
10
  module RatatuiRuby
11
11
  module TestHelper
12
12
  module EventInjection
13
- def inject_event: (Event::Base event) -> void
13
+ def inject_event: (Event event) -> void
14
14
  def inject_mouse: (x: Integer, y: Integer, ?kind: Symbol, ?modifiers: Array[String], ?button: Symbol) -> void
15
15
  def inject_click: (x: Integer, y: Integer, ?modifiers: Array[String]) -> void
16
16
  def inject_right_click: (x: Integer, y: Integer, ?modifiers: Array[String]) -> void
17
17
  def inject_drag: (x: Integer, y: Integer, ?modifiers: Array[String], ?button: Symbol) -> void
18
- def inject_keys: (*(String | Symbol | (Hash[Symbol, untyped]) | Event::Key) args) -> void
18
+ def inject_keys: (*(String | Symbol | { code: String, ?modifiers: Array[String] } | Event::Key) args) -> void
19
19
  alias inject_key inject_keys
20
20
  end
21
21
  end
@@ -10,9 +10,28 @@
10
10
  module RatatuiRuby
11
11
  module TestHelper
12
12
  module Snapshot
13
- def assert_snapshot: (String name, ?String? msg) ?{ (Array[String]) -> Array[String] } -> void
14
- def assert_screen_matches: (String | Array[String] expected, ?String? msg) ?{ (Array[String]) -> Array[String] } -> void
15
- def assert_rich_snapshot: (String name, ?String? msg) ?{ (Array[String]) -> Array[String] } -> void
13
+ include ::Minitest::Assertions
14
+
15
+ # Public assertions
16
+ def assert_plain_snapshot: (String name, ?String? msg, ?snapshot_dir: String?) ?{ (Array[String]) -> Array[String] } -> void
17
+ def assert_screen_matches: ((String | Array[String]) expected, ?String? msg) ?{ (Array[String]) -> Array[String] } -> void
18
+ def assert_rich_snapshot: (String name, ?String? msg, ?snapshot_dir: String?) ?{ (Array[String]) -> Array[String] } -> void
19
+ def assert_snapshots: (String name, ?String? msg) ?{ (Array[String]) -> Array[String] } -> void
20
+ def render_rich_buffer: () -> String
21
+
22
+ # Methods available via mixin context (from Minitest::Assertions)
23
+ # untyped: assert_equal from Minitest compares any two values
24
+ def assert_equal: (untyped expected, untyped actual, ?String? msg) -> void
25
+
26
+ # Methods available via mixin context (from Terminal)
27
+ def buffer_content: () -> Array[String]
28
+
29
+ private
30
+
31
+ def _render_buffer_with_ansi: () -> String
32
+ def _ansi_for_color: ((Symbol | String)?, Symbol layer) -> String
33
+ def _ansi_named_color: (Symbol name, bool is_fg) -> String
34
+ def _ansi_for_modifiers: (Array[Symbol]?) -> String
16
35
  end
17
36
  end
18
37
  end
@@ -7,12 +7,19 @@
7
7
 
8
8
  # SPDX-License-Identifier: AGPL-3.0-or-later
9
9
 
10
+ # untyped: **untyped splat - assertions accept any attribute combination (fg, bg, bold, etc.)
11
+
10
12
  module RatatuiRuby
11
13
  module TestHelper
12
14
  module StyleAssertions
15
+ include ::Minitest::Assertions
16
+
17
+ # From Terminal module
18
+ def get_cell: (Integer x, Integer y) -> Hash[Symbol, untyped]
19
+
13
20
  def assert_cell_style: (Integer x, Integer y, **untyped expected_attributes) -> void
14
21
  def assert_color: (Symbol | Integer | String expected, x: Integer, y: Integer, ?layer: Symbol) -> void
15
- def assert_area_style: (Rect | Hash[Symbol, Integer] area, **untyped attributes) -> void
22
+ def assert_area_style: (Layout::Rect | Hash[Symbol, Integer] area, **untyped attributes) -> void
16
23
  def assert_fg_color: (Symbol | Integer | String expected, Integer x, Integer y) -> void
17
24
  alias assert_fg assert_fg_color
18
25
  def assert_bg_color: (Symbol | Integer | String expected, Integer x, Integer y) -> void
@@ -7,13 +7,16 @@
7
7
 
8
8
  # SPDX-License-Identifier: AGPL-3.0-or-later
9
9
 
10
+ # untyped: widget parameter/storage - test mocks accept any widget type for flexibility
11
+
10
12
  module RatatuiRuby
11
13
  module TestHelper
12
14
  module TestDoubles
13
15
  class MockFrame < Data
14
- attr_accessor rendered_widgets: Array[{ widget: untyped, area: Rect }]
15
- def self.new: (?rendered_widgets: Array[{ widget: untyped, area: Rect }]) -> MockFrame
16
- def render_widget: (untyped widget, Rect area) -> void
16
+ attr_accessor rendered_widgets: Array[{ widget: untyped, area: Layout::Rect }]
17
+ def self.new: (?rendered_widgets: Array[{ widget: untyped, area: Layout::Rect }]) -> MockFrame
18
+ def initialize: (?rendered_widgets: Array[{ widget: untyped, area: Layout::Rect }]) -> void
19
+ def render_widget: (untyped widget, Layout::Rect area) -> void
17
20
  end
18
21
 
19
22
  class StubRect < Data
@@ -22,6 +25,7 @@ module RatatuiRuby
22
25
  attr_accessor width: Integer
23
26
  attr_accessor height: Integer
24
27
  def self.new: (?x: Integer, ?y: Integer, ?width: Integer, ?height: Integer) -> StubRect
28
+ def initialize: (?x: Integer, ?y: Integer, ?width: Integer, ?height: Integer) -> void
25
29
  end
26
30
  end
27
31
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ module Text
10
+ class Line < Data
11
+ attr_reader spans: Array[Span]
12
+ attr_reader alignment: Symbol?
13
+ attr_reader style: Style::Style?
14
+
15
+ def self.new: (?spans: Array[Span], ?alignment: Symbol?, ?style: Style::Style?) -> Line
16
+ def initialize: (?spans: Array[Span], ?alignment: Symbol?, ?style: Style::Style?) -> void
17
+ def self.from_string: (String, ?alignment: Symbol?) -> Line
18
+ def width: () -> Integer
19
+ def left_aligned: () -> Line
20
+ def centered: () -> Line
21
+ def right_aligned: () -> Line
22
+ def push_span: (Span) -> Line
23
+ def patch_style: (Style::Style?) -> Line
24
+ def reset_style: () -> Line
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ module Text
10
+ class Span < Data
11
+ attr_reader content: String
12
+ attr_reader style: Style::Style?
13
+
14
+ def self.new: (content: String, ?style: Style::Style?) -> Span
15
+ def initialize: (content: String, ?style: Style::Style?) -> void
16
+ def self.styled: (String, ?Style?) -> Span
17
+ def width: () -> Integer
18
+ def self.raw: (String) -> Span
19
+ def patch_style: (Style::Style?) -> Span
20
+ def reset_style: () -> Span
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ module Text
10
+ def self.width: (String) -> Integer
11
+ end
12
+ end
@@ -10,7 +10,7 @@
10
10
  module RatatuiRuby
11
11
  class TUI
12
12
  module BufferFactories
13
- def cell: (?char: String?, ?fg: Symbol?, ?bg: Symbol?, ?modifiers: Array[Symbol]?) -> Buffer::Cell
13
+ def cell: (?symbol: String?, ?char: String?, ?fg: (Symbol | String | nil), ?bg: (Symbol | String | nil), ?modifiers: Array[String]) -> Buffer::Cell
14
14
  end
15
15
  end
16
16
  end
@@ -10,11 +10,29 @@
10
10
  module RatatuiRuby
11
11
  class TUI
12
12
  module CanvasFactories
13
- def shape_map: (**top) -> Widgets::Shape::Map
14
- def shape_line: (**top) -> Widgets::Shape::Line
15
- def shape_point: (**top) -> Widgets::Shape::Point
16
- def shape_circle: (**top) -> Widgets::Shape::Circle
17
- def shape_rectangle: (**top) -> Widgets::Shape::Rectangle
13
+ # Core shape methods
14
+ def shape_map: (?color: (String | Symbol), ?resolution: Symbol) -> Widgets::Shape::Map
15
+ def shape_line: (x1: _ToF, y1: _ToF, x2: _ToF, y2: _ToF, color: (String | Symbol)) -> Widgets::Shape::Line
16
+ def shape_point: (x: _ToF, y: _ToF) -> Widgets::Shape::Point
17
+ def shape_circle: (x: _ToF, y: _ToF, radius: _ToF, color: (String | Symbol)) -> Widgets::Shape::Circle
18
+ def shape_rectangle: (x: _ToF, y: _ToF, width: _ToF, height: _ToF, color: (String | Symbol)) -> Widgets::Shape::Rectangle
19
+ def shape_label: (x: _ToF, y: _ToF, ?text: String?, ?line: Text::Line?) -> Widgets::Shape::Label
20
+
21
+ # Terse aliases (DWIM) - no rectangle to avoid confusion with Layout::Rect
22
+ alias circle shape_circle
23
+ alias point shape_point
24
+ alias map shape_map
25
+ def label: (?untyped first, **untyped kwargs) -> Widgets::Shape::Label
26
+
27
+ # Bidirectional aliases (*_shape)
28
+ alias circle_shape shape_circle
29
+ alias point_shape shape_point
30
+ alias rectangle_shape shape_rectangle
31
+ alias map_shape shape_map
32
+ alias label_shape label
33
+
34
+ # Shape dispatcher (TIMTOWTDI pattern)
35
+ def shape: (Symbol, **untyped) -> untyped
18
36
  end
19
37
  end
20
38
  end
@@ -10,9 +10,9 @@
10
10
  module RatatuiRuby
11
11
  class TUI
12
12
  module Core
13
- def draw: (?Widgets::_Widget? tree) -> void
13
+ def draw: (?widget? tree) -> void
14
14
  | () { (Frame) -> void } -> void
15
- def poll_event: (?timeout: Float) -> Event::event
15
+ def poll_event: (?timeout: Float) -> Event?
16
16
  def get_cell_at: (Integer x, Integer y) -> Buffer::Cell
17
17
  def draw_cell: (Integer x, Integer y, Buffer::Cell cell) -> Draw::CellCmd
18
18
  end
@@ -11,15 +11,29 @@ module RatatuiRuby
11
11
  class TUI
12
12
  module LayoutFactories
13
13
  def rect: (?x: Integer, ?y: Integer, ?width: Integer, ?height: Integer) -> Layout::Rect
14
- def constraint: (**top) -> Layout::Constraint
14
+
15
+ # Constraint dispatcher (TIMTOWTDI pattern)
16
+ def constraint: (?type: Symbol, ?value: (Integer | Array[Integer])) -> Layout::Constraint
17
+ | (:length | :fixed, Integer) -> Layout::Constraint
18
+ | (:percentage | :percent, Integer) -> Layout::Constraint
19
+ | (:min, Integer) -> Layout::Constraint
20
+ | (:max, Integer) -> Layout::Constraint
21
+ | (:fill | :flex | :fr, ?Integer) -> Layout::Constraint
22
+ | (:ratio | :aspect, Integer, Integer) -> Layout::Constraint
23
+
15
24
  def constraint_length: (Integer n) -> Layout::Constraint
16
25
  def constraint_percentage: (Integer n) -> Layout::Constraint
17
26
  def constraint_min: (Integer n) -> Layout::Constraint
18
27
  def constraint_max: (Integer n) -> Layout::Constraint
19
28
  def constraint_fill: (?Integer n) -> Layout::Constraint
20
29
  def constraint_ratio: (Integer numerator, Integer denominator) -> Layout::Constraint
21
- def layout: (**top) -> Layout::Layout
30
+ def layout: (?direction: Symbol, ?constraints: Array[Layout::Constraint], ?children: Array[widget], ?flex: Layout::flex_mode) -> Layout::Layout
22
31
  def layout_split: (Layout::Rect area, ?direction: Symbol, constraints: Array[Layout::Constraint], ?flex: Symbol) -> Array[Layout::Rect]
32
+ def split: (Layout::Rect area, ?direction: Symbol, constraints: Array[Layout::Constraint], ?flex: Symbol) -> Array[Layout::Rect]
33
+ def fixed: (Integer n) -> Layout::Constraint
34
+ def percent: (Integer n) -> Layout::Constraint
35
+ def flex: (?Integer n) -> Layout::Constraint
36
+ def fr: (?Integer n) -> Layout::Constraint
23
37
  end
24
38
  end
25
39
  end
@@ -10,9 +10,14 @@
10
10
  module RatatuiRuby
11
11
  class TUI
12
12
  module StateFactories
13
- def list_state: (**top) -> ListState
14
- def table_state: (**top) -> TableState
15
- def scrollbar_state: (**top) -> ScrollbarState
13
+ def list_state: (?Integer? selected) -> ListState
14
+ def table_state: (?Integer? selected) -> TableState
15
+ def scrollbar_state: (?Integer content_length) -> ScrollbarState
16
+
17
+ # State dispatcher (TIMTOWTDI pattern)
18
+ def state: (:list, ?Integer? arg) -> ListState
19
+ | (:table, ?Integer? arg) -> TableState
20
+ | (:scrollbar, ?Integer arg) -> ScrollbarState
16
21
  end
17
22
  end
18
23
  end
@@ -10,7 +10,9 @@
10
10
  module RatatuiRuby
11
11
  class TUI
12
12
  module StyleFactories
13
- def style: (?fg: Symbol?, ?bg: Symbol?, ?modifiers: Array[Symbol]?) -> Style::Style
13
+ type color = String | Symbol | Integer
14
+
15
+ def style: (?fg: color?, ?bg: color?, ?underline_color: color?, ?modifiers: Array[Symbol], ?remove_modifiers: Array[Symbol]) -> Style::Style
14
16
  end
15
17
  end
16
18
  end
@@ -10,11 +10,14 @@
10
10
  module RatatuiRuby
11
11
  class TUI
12
12
  module TextFactories
13
- def text_span: (?content: String, ?style: Style::Style?) -> Text::Span
14
- def span: (?content: String, ?style: Style::Style?) -> Text::Span
15
- def text_line: (?spans: Array[Text::Span], ?alignment: Symbol?) -> Text::Line
16
- def line: (?spans: Array[Text::Span], ?alignment: Symbol?) -> Text::Line
13
+ def text_span: (content: String, ?style: Style::Style?) -> Text::Span
14
+ def span: (content: String, ?style: Style::Style?) -> Text::Span
15
+ def text_line: (?spans: Array[Text::Span], ?alignment: Symbol?, ?style: Style::Style?) -> Text::Line
16
+ def line: (?spans: Array[Text::Span], ?alignment: Symbol?, ?style: Style::Style?) -> Text::Line
17
17
  def text_width: (String string) -> Integer
18
+
19
+ # Text dispatcher (TIMTOWTDI pattern)
20
+ def text: (Symbol, **untyped) -> (Text::Span | Text::Line)
18
21
  end
19
22
  end
20
23
  end