ratatui_ruby 1.4.0-x86_64-linux

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 (292) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +15 -0
  3. data/LICENSES/AGPL-3.0-or-later.txt +661 -0
  4. data/LICENSES/CC-BY-SA-4.0.txt +427 -0
  5. data/LICENSES/CC0-1.0.txt +121 -0
  6. data/LICENSES/LGPL-3.0-or-later.txt +304 -0
  7. data/LICENSES/MIT-0.txt +16 -0
  8. data/LICENSES/MIT.txt +21 -0
  9. data/REUSE.toml +42 -0
  10. data/exe/.gitkeep +0 -0
  11. data/ext/ratatui_ruby/.cargo/config.toml +13 -0
  12. data/ext/ratatui_ruby/.gitignore +4 -0
  13. data/ext/ratatui_ruby/Cargo.lock +1737 -0
  14. data/ext/ratatui_ruby/Cargo.toml +24 -0
  15. data/ext/ratatui_ruby/clippy.toml +7 -0
  16. data/ext/ratatui_ruby/extconf.rb +21 -0
  17. data/ext/ratatui_ruby/src/color.rs +82 -0
  18. data/ext/ratatui_ruby/src/errors.rs +28 -0
  19. data/ext/ratatui_ruby/src/events.rs +700 -0
  20. data/ext/ratatui_ruby/src/frame.rs +241 -0
  21. data/ext/ratatui_ruby/src/lib.rs +343 -0
  22. data/ext/ratatui_ruby/src/lib_header.rs +11 -0
  23. data/ext/ratatui_ruby/src/rendering.rs +158 -0
  24. data/ext/ratatui_ruby/src/string_width.rs +101 -0
  25. data/ext/ratatui_ruby/src/style.rs +469 -0
  26. data/ext/ratatui_ruby/src/terminal/capabilities.rs +46 -0
  27. data/ext/ratatui_ruby/src/terminal/init.rs +233 -0
  28. data/ext/ratatui_ruby/src/terminal/mod.rs +42 -0
  29. data/ext/ratatui_ruby/src/terminal/mutations.rs +158 -0
  30. data/ext/ratatui_ruby/src/terminal/queries.rs +231 -0
  31. data/ext/ratatui_ruby/src/terminal/query.rs +400 -0
  32. data/ext/ratatui_ruby/src/terminal/storage.rs +109 -0
  33. data/ext/ratatui_ruby/src/terminal/wrapper.rs +16 -0
  34. data/ext/ratatui_ruby/src/text.rs +225 -0
  35. data/ext/ratatui_ruby/src/widgets/barchart.rs +169 -0
  36. data/ext/ratatui_ruby/src/widgets/block.rs +41 -0
  37. data/ext/ratatui_ruby/src/widgets/calendar.rs +84 -0
  38. data/ext/ratatui_ruby/src/widgets/canvas.rs +183 -0
  39. data/ext/ratatui_ruby/src/widgets/center.rs +79 -0
  40. data/ext/ratatui_ruby/src/widgets/chart.rs +222 -0
  41. data/ext/ratatui_ruby/src/widgets/clear.rs +39 -0
  42. data/ext/ratatui_ruby/src/widgets/cursor.rs +32 -0
  43. data/ext/ratatui_ruby/src/widgets/gauge.rs +65 -0
  44. data/ext/ratatui_ruby/src/widgets/layout.rs +379 -0
  45. data/ext/ratatui_ruby/src/widgets/line_gauge.rs +100 -0
  46. data/ext/ratatui_ruby/src/widgets/list.rs +378 -0
  47. data/ext/ratatui_ruby/src/widgets/list_state.rs +173 -0
  48. data/ext/ratatui_ruby/src/widgets/mod.rs +26 -0
  49. data/ext/ratatui_ruby/src/widgets/overlay.rs +24 -0
  50. data/ext/ratatui_ruby/src/widgets/paragraph.rs +87 -0
  51. data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
  52. data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +55 -0
  53. data/ext/ratatui_ruby/src/widgets/scrollbar.rs +214 -0
  54. data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
  55. data/ext/ratatui_ruby/src/widgets/sparkline.rs +127 -0
  56. data/ext/ratatui_ruby/src/widgets/table.rs +415 -0
  57. data/ext/ratatui_ruby/src/widgets/table_state.rs +203 -0
  58. data/ext/ratatui_ruby/src/widgets/tabs.rs +194 -0
  59. data/lib/ratatui_ruby/backend/window_size.rb +50 -0
  60. data/lib/ratatui_ruby/backend.rb +59 -0
  61. data/lib/ratatui_ruby/buffer/cell.rb +212 -0
  62. data/lib/ratatui_ruby/buffer.rb +149 -0
  63. data/lib/ratatui_ruby/cell.rb +208 -0
  64. data/lib/ratatui_ruby/debug.rb +215 -0
  65. data/lib/ratatui_ruby/draw.rb +63 -0
  66. data/lib/ratatui_ruby/event/focus_gained.rb +125 -0
  67. data/lib/ratatui_ruby/event/focus_lost.rb +127 -0
  68. data/lib/ratatui_ruby/event/key/character.rb +53 -0
  69. data/lib/ratatui_ruby/event/key/dwim.rb +301 -0
  70. data/lib/ratatui_ruby/event/key/media.rb +46 -0
  71. data/lib/ratatui_ruby/event/key/modifier.rb +107 -0
  72. data/lib/ratatui_ruby/event/key/navigation.rb +72 -0
  73. data/lib/ratatui_ruby/event/key/system.rb +47 -0
  74. data/lib/ratatui_ruby/event/key.rb +479 -0
  75. data/lib/ratatui_ruby/event/mouse.rb +291 -0
  76. data/lib/ratatui_ruby/event/none.rb +53 -0
  77. data/lib/ratatui_ruby/event/paste.rb +130 -0
  78. data/lib/ratatui_ruby/event/resize.rb +221 -0
  79. data/lib/ratatui_ruby/event/sync.rb +52 -0
  80. data/lib/ratatui_ruby/event.rb +163 -0
  81. data/lib/ratatui_ruby/frame.rb +257 -0
  82. data/lib/ratatui_ruby/labs/a11y.rb +182 -0
  83. data/lib/ratatui_ruby/labs/frame_a11y_capture.rb +50 -0
  84. data/lib/ratatui_ruby/labs.rb +47 -0
  85. data/lib/ratatui_ruby/layout/alignment.rb +91 -0
  86. data/lib/ratatui_ruby/layout/constraint.rb +337 -0
  87. data/lib/ratatui_ruby/layout/layout.rb +258 -0
  88. data/lib/ratatui_ruby/layout/position.rb +81 -0
  89. data/lib/ratatui_ruby/layout/rect.rb +733 -0
  90. data/lib/ratatui_ruby/layout/size.rb +62 -0
  91. data/lib/ratatui_ruby/layout.rb +29 -0
  92. data/lib/ratatui_ruby/list_state.rb +201 -0
  93. data/lib/ratatui_ruby/output_guard.rb +171 -0
  94. data/lib/ratatui_ruby/ratatui_ruby.so +0 -0
  95. data/lib/ratatui_ruby/scrollbar_state.rb +122 -0
  96. data/lib/ratatui_ruby/style/color.rb +149 -0
  97. data/lib/ratatui_ruby/style/style.rb +147 -0
  98. data/lib/ratatui_ruby/style.rb +19 -0
  99. data/lib/ratatui_ruby/symbols.rb +435 -0
  100. data/lib/ratatui_ruby/synthetic_events.rb +106 -0
  101. data/lib/ratatui_ruby/table_state.rb +251 -0
  102. data/lib/ratatui_ruby/terminal/capabilities.rb +316 -0
  103. data/lib/ratatui_ruby/terminal/viewport.rb +80 -0
  104. data/lib/ratatui_ruby/terminal.rb +66 -0
  105. data/lib/ratatui_ruby/terminal_lifecycle.rb +303 -0
  106. data/lib/ratatui_ruby/terminal_lifecycle.rb.bak +197 -0
  107. data/lib/ratatui_ruby/test_helper/event_injection.rb +241 -0
  108. data/lib/ratatui_ruby/test_helper/global_state.rb +111 -0
  109. data/lib/ratatui_ruby/test_helper/snapshot.rb +568 -0
  110. data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.ansi +24 -0
  111. data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.txt +24 -0
  112. data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.ansi +5 -0
  113. data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.txt +5 -0
  114. data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.ansi +24 -0
  115. data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.txt +24 -0
  116. data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.ansi +12 -0
  117. data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.txt +12 -0
  118. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.ansi +12 -0
  119. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.txt +12 -0
  120. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.ansi +12 -0
  121. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.txt +12 -0
  122. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.ansi +12 -0
  123. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.txt +12 -0
  124. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.ansi +12 -0
  125. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.txt +12 -0
  126. data/lib/ratatui_ruby/test_helper/snapshots/my_snapshot.txt +1 -0
  127. data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.ansi +10 -0
  128. data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.txt +10 -0
  129. data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.ansi +10 -0
  130. data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.txt +10 -0
  131. data/lib/ratatui_ruby/test_helper/style_assertions.rb +449 -0
  132. data/lib/ratatui_ruby/test_helper/subprocess_timeout.rb +35 -0
  133. data/lib/ratatui_ruby/test_helper/terminal.rb +187 -0
  134. data/lib/ratatui_ruby/test_helper/test_doubles.rb +86 -0
  135. data/lib/ratatui_ruby/test_helper.rb +115 -0
  136. data/lib/ratatui_ruby/text/line.rb +245 -0
  137. data/lib/ratatui_ruby/text/span.rb +158 -0
  138. data/lib/ratatui_ruby/text.rb +99 -0
  139. data/lib/ratatui_ruby/tui/buffer_factories.rb +22 -0
  140. data/lib/ratatui_ruby/tui/canvas_factories.rb +149 -0
  141. data/lib/ratatui_ruby/tui/core.rb +67 -0
  142. data/lib/ratatui_ruby/tui/layout_factories.rb +153 -0
  143. data/lib/ratatui_ruby/tui/state_factories.rb +77 -0
  144. data/lib/ratatui_ruby/tui/style_factories.rb +22 -0
  145. data/lib/ratatui_ruby/tui/text_factories.rb +86 -0
  146. data/lib/ratatui_ruby/tui/widget_factories.rb +272 -0
  147. data/lib/ratatui_ruby/tui.rb +106 -0
  148. data/lib/ratatui_ruby/version.rb +12 -0
  149. data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +51 -0
  150. data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +29 -0
  151. data/lib/ratatui_ruby/widgets/bar_chart.rb +308 -0
  152. data/lib/ratatui_ruby/widgets/block.rb +266 -0
  153. data/lib/ratatui_ruby/widgets/calendar.rb +88 -0
  154. data/lib/ratatui_ruby/widgets/canvas.rb +297 -0
  155. data/lib/ratatui_ruby/widgets/cell.rb +59 -0
  156. data/lib/ratatui_ruby/widgets/center.rb +71 -0
  157. data/lib/ratatui_ruby/widgets/chart.rb +172 -0
  158. data/lib/ratatui_ruby/widgets/clear.rb +66 -0
  159. data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
  160. data/lib/ratatui_ruby/widgets/cursor.rb +54 -0
  161. data/lib/ratatui_ruby/widgets/gauge.rb +146 -0
  162. data/lib/ratatui_ruby/widgets/line_gauge.rb +158 -0
  163. data/lib/ratatui_ruby/widgets/list.rb +252 -0
  164. data/lib/ratatui_ruby/widgets/list_item.rb +55 -0
  165. data/lib/ratatui_ruby/widgets/overlay.rb +55 -0
  166. data/lib/ratatui_ruby/widgets/paragraph.rb +113 -0
  167. data/lib/ratatui_ruby/widgets/ratatui_logo.rb +35 -0
  168. data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +40 -0
  169. data/lib/ratatui_ruby/widgets/row.rb +123 -0
  170. data/lib/ratatui_ruby/widgets/scrollbar.rb +147 -0
  171. data/lib/ratatui_ruby/widgets/shape/label.rb +80 -0
  172. data/lib/ratatui_ruby/widgets/sparkline.rb +153 -0
  173. data/lib/ratatui_ruby/widgets/table.rb +213 -0
  174. data/lib/ratatui_ruby/widgets/tabs.rb +91 -0
  175. data/lib/ratatui_ruby/widgets.rb +43 -0
  176. data/lib/ratatui_ruby.rb +555 -0
  177. data/sig/examples/app_all_events/app.rbs +11 -0
  178. data/sig/examples/app_all_events/model/app_model.rbs +23 -0
  179. data/sig/examples/app_all_events/model/event_entry.rbs +23 -0
  180. data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
  181. data/sig/examples/app_all_events/view/app_view.rbs +8 -0
  182. data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
  183. data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
  184. data/sig/examples/app_all_events/view/live_view.rbs +6 -0
  185. data/sig/examples/app_all_events/view/log_view.rbs +6 -0
  186. data/sig/examples/app_all_events/view.rbs +14 -0
  187. data/sig/examples/app_cli_rich_moments/app.rbs +12 -0
  188. data/sig/examples/app_color_picker/app.rbs +17 -0
  189. data/sig/examples/app_external_editor/app.rbs +12 -0
  190. data/sig/examples/app_login_form/app.rbs +11 -0
  191. data/sig/examples/app_stateful_interaction/app.rbs +39 -0
  192. data/sig/examples/verify_quickstart_dsl/app.rbs +17 -0
  193. data/sig/examples/verify_quickstart_lifecycle/app.rbs +17 -0
  194. data/sig/examples/verify_readme_usage/app.rbs +17 -0
  195. data/sig/examples/widget_block_demo/app.rbs +38 -0
  196. data/sig/examples/widget_box_demo/app.rbs +17 -0
  197. data/sig/examples/widget_calendar_demo/app.rbs +17 -0
  198. data/sig/examples/widget_cell_demo/app.rbs +17 -0
  199. data/sig/examples/widget_chart_demo/app.rbs +17 -0
  200. data/sig/examples/widget_gauge_demo/app.rbs +17 -0
  201. data/sig/examples/widget_layout_split/app.rbs +16 -0
  202. data/sig/examples/widget_line_gauge_demo/app.rbs +17 -0
  203. data/sig/examples/widget_list_demo/app.rbs +17 -0
  204. data/sig/examples/widget_map_demo/app.rbs +17 -0
  205. data/sig/examples/widget_popup_demo/app.rbs +17 -0
  206. data/sig/examples/widget_ratatui_logo_demo/app.rbs +17 -0
  207. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +17 -0
  208. data/sig/examples/widget_rect/app.rbs +18 -0
  209. data/sig/examples/widget_render/app.rbs +16 -0
  210. data/sig/examples/widget_rich_text/app.rbs +17 -0
  211. data/sig/examples/widget_scroll_text/app.rbs +17 -0
  212. data/sig/examples/widget_scrollbar_demo/app.rbs +17 -0
  213. data/sig/examples/widget_sparkline_demo/app.rbs +16 -0
  214. data/sig/examples/widget_style_colors/app.rbs +20 -0
  215. data/sig/examples/widget_table_demo/app.rbs +17 -0
  216. data/sig/examples/widget_text_width/app.rbs +16 -0
  217. data/sig/generated/event_key_predicates.rbs +1348 -0
  218. data/sig/manifest.yaml +5 -0
  219. data/sig/patches/data.rbs +26 -0
  220. data/sig/patches/debugger__.rbs +8 -0
  221. data/sig/ratatui_ruby/backend/window_size.rbs +17 -0
  222. data/sig/ratatui_ruby/backend.rbs +12 -0
  223. data/sig/ratatui_ruby/buffer/cell.rbs +46 -0
  224. data/sig/ratatui_ruby/buffer.rbs +18 -0
  225. data/sig/ratatui_ruby/cell.rbs +44 -0
  226. data/sig/ratatui_ruby/clear.rbs +18 -0
  227. data/sig/ratatui_ruby/constraint.rbs +26 -0
  228. data/sig/ratatui_ruby/debug.rbs +45 -0
  229. data/sig/ratatui_ruby/draw.rbs +30 -0
  230. data/sig/ratatui_ruby/event.rbs +249 -0
  231. data/sig/ratatui_ruby/frame.rbs +23 -0
  232. data/sig/ratatui_ruby/interfaces.rbs +25 -0
  233. data/sig/ratatui_ruby/labs.rbs +90 -0
  234. data/sig/ratatui_ruby/layout/alignment.rbs +26 -0
  235. data/sig/ratatui_ruby/layout/constraint.rbs +39 -0
  236. data/sig/ratatui_ruby/layout/layout.rbs +45 -0
  237. data/sig/ratatui_ruby/layout/position.rbs +18 -0
  238. data/sig/ratatui_ruby/layout/rect.rbs +64 -0
  239. data/sig/ratatui_ruby/layout/size.rbs +18 -0
  240. data/sig/ratatui_ruby/list_state.rbs +23 -0
  241. data/sig/ratatui_ruby/output_guard.rbs +23 -0
  242. data/sig/ratatui_ruby/ratatui_ruby.rbs +113 -0
  243. data/sig/ratatui_ruby/rect.rbs +17 -0
  244. data/sig/ratatui_ruby/scrollbar_state.rbs +24 -0
  245. data/sig/ratatui_ruby/session.rbs +93 -0
  246. data/sig/ratatui_ruby/style/color.rbs +22 -0
  247. data/sig/ratatui_ruby/style/style.rbs +29 -0
  248. data/sig/ratatui_ruby/symbols.rbs +141 -0
  249. data/sig/ratatui_ruby/synthetic_events.rbs +24 -0
  250. data/sig/ratatui_ruby/table_state.rbs +27 -0
  251. data/sig/ratatui_ruby/terminal/capabilities.rbs +38 -0
  252. data/sig/ratatui_ruby/terminal/viewport.rbs +33 -0
  253. data/sig/ratatui_ruby/terminal_lifecycle.rbs +39 -0
  254. data/sig/ratatui_ruby/test_helper/event_injection.rbs +22 -0
  255. data/sig/ratatui_ruby/test_helper/snapshot.rbs +37 -0
  256. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +77 -0
  257. data/sig/ratatui_ruby/test_helper/terminal.rbs +20 -0
  258. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +32 -0
  259. data/sig/ratatui_ruby/test_helper.rbs +18 -0
  260. data/sig/ratatui_ruby/text/line.rbs +27 -0
  261. data/sig/ratatui_ruby/text/span.rbs +23 -0
  262. data/sig/ratatui_ruby/text.rbs +12 -0
  263. data/sig/ratatui_ruby/tui/buffer_factories.rbs +16 -0
  264. data/sig/ratatui_ruby/tui/canvas_factories.rbs +38 -0
  265. data/sig/ratatui_ruby/tui/core.rbs +23 -0
  266. data/sig/ratatui_ruby/tui/layout_factories.rbs +39 -0
  267. data/sig/ratatui_ruby/tui/state_factories.rbs +23 -0
  268. data/sig/ratatui_ruby/tui/style_factories.rbs +18 -0
  269. data/sig/ratatui_ruby/tui/text_factories.rbs +23 -0
  270. data/sig/ratatui_ruby/tui/widget_factories.rbs +138 -0
  271. data/sig/ratatui_ruby/tui.rbs +25 -0
  272. data/sig/ratatui_ruby/version.rbs +12 -0
  273. data/sig/ratatui_ruby/widgets/bar_chart.rbs +95 -0
  274. data/sig/ratatui_ruby/widgets/block.rbs +51 -0
  275. data/sig/ratatui_ruby/widgets/calendar.rbs +45 -0
  276. data/sig/ratatui_ruby/widgets/canvas.rbs +95 -0
  277. data/sig/ratatui_ruby/widgets/chart.rbs +91 -0
  278. data/sig/ratatui_ruby/widgets/coerceable_widget.rbs +26 -0
  279. data/sig/ratatui_ruby/widgets/gauge.rbs +44 -0
  280. data/sig/ratatui_ruby/widgets/line_gauge.rbs +48 -0
  281. data/sig/ratatui_ruby/widgets/list.rbs +63 -0
  282. data/sig/ratatui_ruby/widgets/misc.rbs +158 -0
  283. data/sig/ratatui_ruby/widgets/paragraph.rbs +45 -0
  284. data/sig/ratatui_ruby/widgets/row.rbs +43 -0
  285. data/sig/ratatui_ruby/widgets/scrollbar.rbs +53 -0
  286. data/sig/ratatui_ruby/widgets/shape/label.rbs +37 -0
  287. data/sig/ratatui_ruby/widgets/sparkline.rbs +45 -0
  288. data/sig/ratatui_ruby/widgets/table.rbs +78 -0
  289. data/sig/ratatui_ruby/widgets/tabs.rbs +44 -0
  290. data/sig/ratatui_ruby/widgets.rbs +16 -0
  291. data/vendor/goodcop/base.yml +1047 -0
  292. metadata +729 -0
@@ -0,0 +1,55 @@
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 Widgets
10
+ # A styled list item combining content with optional style.
11
+ #
12
+ # By default, List items are strings. For more control over styling individual rows,
13
+ # wrap the content in a ListItem to apply a style specific to that item.
14
+ #
15
+ # The content can be a String, Text::Span, or Text::Line. The style applies to the
16
+ # entire row background.
17
+ #
18
+ # === Examples
19
+ #
20
+ #--
21
+ # SPDX-SnippetBegin
22
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
23
+ # SPDX-License-Identifier: MIT-0
24
+ #++
25
+ # # Item with red background
26
+ # ListItem.new(content: "Error", style: Style.new(bg: :red))
27
+ #
28
+ # # Item with styled content
29
+ # ListItem.new(
30
+ # content: Text::Span.new(content: "Status: OK", style: Style.new(fg: :green, modifiers: [:bold]))
31
+ # )
32
+ #--
33
+ # SPDX-SnippetEnd
34
+ #++
35
+ class ListItem < Data.define(:content, :style)
36
+ include CoerceableWidget
37
+
38
+ ##
39
+ # :attr_reader: content
40
+ # The content to display (String, Text::Span, or Text::Line).
41
+
42
+ ##
43
+ # :attr_reader: style
44
+ # The style to apply to the item (optional Style).
45
+
46
+ # Creates a new ListItem.
47
+ #
48
+ # [content] String, Text::Span, or Text::Line.
49
+ # [style] Style object (optional).
50
+ def initialize(content:, style: nil)
51
+ super
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,55 @@
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 Widgets
10
+ # Stacks widgets on top of each other.
11
+ #
12
+ # Terminal interfaces are 2D grids, but complex UIs require depth. You need to float modals over text,
13
+ # or place a status bar on top of a map.
14
+ #
15
+ # This widget manages the Z-axis. It renders a list of widgets sequentially into the same area.
16
+ # Later widgets draw over earlier ones (Painter's Algorithm).
17
+ #
18
+ # Use overlays to compose complex scenes. Combine backgrounds, main content, and floating elements.
19
+ #
20
+ # === Examples
21
+ #
22
+ #--
23
+ # SPDX-SnippetBegin
24
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
25
+ # SPDX-License-Identifier: MIT-0
26
+ #++
27
+ # Overlay.new(
28
+ # layers: [
29
+ # BackgroundMap.new,
30
+ # StatusBar.new, # Draws over map
31
+ # ModalDialog.new # Draws over everything
32
+ # ]
33
+ # )
34
+ #--
35
+ # SPDX-SnippetEnd
36
+ #++
37
+ class Overlay < Data.define(:layers)
38
+ include CoerceableWidget
39
+
40
+ ##
41
+ # :attr_reader: layers
42
+ # The stack of widgets to render.
43
+ #
44
+ # Rendered from index 0 to N. Index N is the top-most layer.
45
+
46
+ # Creates a new Overlay.
47
+ #
48
+ # [layers]
49
+ # Array of widgets.
50
+ def initialize(layers: [])
51
+ super
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,113 @@
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 Widgets
10
+ # Displays a block of text.
11
+ #
12
+ # Raw strings are insufficient for UIs. They overflow constraints. They don't respect alignment (left, center, right).
13
+ #
14
+ # This widget creates a smart text container. It wraps content to fit the area. It aligns text as requested. It supports scrolling.
15
+ #
16
+ # Use it for everything from simple labels to complex, multi-paragraph documents.
17
+ #
18
+ # See also: <tt>examples/widget_scroll_text/app.rb</tt> for scrollable paragraphs.
19
+ #
20
+ # === Examples
21
+ #
22
+ #--
23
+ # SPDX-SnippetBegin
24
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
25
+ # SPDX-License-Identifier: MIT-0
26
+ #++
27
+ # # Basic Text
28
+ # Paragraph.new(text: "Hello, World!")
29
+ #
30
+ # # Styled container with wrapping
31
+ # Paragraph.new(
32
+ # text: "This is a long line that will wrap automatically.",
33
+ # style: Style.new(fg: :green),
34
+ # wrap: true,
35
+ # block: Block.new(title: "Output", borders: [:all])
36
+ # )
37
+ #
38
+ # # Scrolling mechanism
39
+ # Paragraph.new(text: large_text, scroll: [scroll_y, 0])
40
+ #--
41
+ # SPDX-SnippetEnd
42
+ #++
43
+ class Paragraph < Data.define(:text, :style, :block, :wrap, :alignment, :scroll)
44
+ include CoerceableWidget
45
+
46
+ ##
47
+ # :attr_reader: text
48
+ # The content to display.
49
+
50
+ ##
51
+ # :attr_reader: style
52
+ # Base style for the text.
53
+
54
+ ##
55
+ # :attr_reader: block
56
+ # Optional wrapping block.
57
+
58
+ ##
59
+ # :attr_reader: wrap
60
+ # Whether to wrap text at the edge of the container (Boolean).
61
+
62
+ ##
63
+ # :attr_reader: alignment
64
+ # Text alignment.
65
+ #
66
+ # <tt>:left</tt>, <tt>:center</tt>, or <tt>:right</tt>.
67
+
68
+ ##
69
+ # :attr_reader: scroll
70
+ # Scroll offset [y, x].
71
+
72
+ # Creates a new Paragraph.
73
+ #
74
+ # [text] String or Text::Line array.
75
+ # [style] Style object.
76
+ # [block] Block object.
77
+ # [wrap] Boolean (default: false).
78
+ # [alignment] Symbol (default: <tt>:left</tt>).
79
+ # [scroll] Array of [y, x] integers (duck-typed via +to_int+).
80
+ def initialize(text:, style: RatatuiRuby::Style::Style.default, block: nil, wrap: false, alignment: :left, scroll: [0, 0])
81
+ super(
82
+ text:,
83
+ style:,
84
+ block:,
85
+ wrap:,
86
+ alignment:,
87
+ scroll: [Integer(scroll[0]), Integer(scroll[1])]
88
+ )
89
+ end
90
+
91
+ # Legacy constructor support.
92
+ def self.new(text:, style: nil, fg: nil, bg: nil, block: nil, wrap: false, alignment: :left, scroll: [0, 0])
93
+ style ||= RatatuiRuby::Style::Style.new(fg:, bg:)
94
+ coerced_scroll = [Integer(scroll[0]), Integer(scroll[1])]
95
+ super(text:, style:, block:, wrap:, alignment:, scroll: coerced_scroll)
96
+ end
97
+
98
+ # Returns the number of lines the paragraph would take up if rendered with the given width.
99
+ #
100
+ # [width] Integer (max width).
101
+ def line_count(width)
102
+ RatatuiRuby.warn_experimental_feature("Paragraph#line_count")
103
+ RatatuiRuby._paragraph_line_count(self, Integer(width))
104
+ end
105
+
106
+ # Returns the minimum width needed to not wrap any text.
107
+ def line_width
108
+ RatatuiRuby.warn_experimental_feature("Paragraph#line_width")
109
+ RatatuiRuby._paragraph_line_width(self)
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,35 @@
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 Widgets
10
+ # Displays the Ratatui logo.
11
+ #
12
+ # Branding is important for identity. Users need to recognize the tools they use.
13
+ #
14
+ # This widget renders the official Ratatui logo.
15
+ #
16
+ # Use it for splash screens, about sections, or terminal dashboards.
17
+ #
18
+ # {rdoc-image:/doc/images/widget_ratatui_logo.png}[link:/examples/widget_ratatui_logo/app_rb.html]
19
+ #
20
+ # === Example
21
+ #
22
+ # Run the interactive demo from the terminal:
23
+ #
24
+ # ruby examples/widget_ratatui_logo/app.rb
25
+ class RatatuiLogo < Data.define
26
+ include CoerceableWidget
27
+
28
+ ##
29
+ # :method: new
30
+ # :call-seq: new -> RatatuiLogo
31
+ #
32
+ # Creates a new RatatuiLogo.
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
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 Widgets
10
+ # Displays the Ratatui mascot.
11
+ #
12
+ # Interfaces without personality feel clinical and dry. Users appreciate a friendly face in their terminal.
13
+ #
14
+ # This widget renders the Ratatui mascot (a mouse).
15
+ #
16
+ # Use it to add charm to your application, greet users on startup, or as a decorative element in sidebars.
17
+ #
18
+ # {rdoc-image:/doc/images/widget_ratatui_mascot.png}[link:/examples/widget_ratatui_mascot/app_rb.html]
19
+ #
20
+ # === Example
21
+ #
22
+ # Run the interactive demo from the terminal:
23
+ #
24
+ # ruby examples/widget_ratatui_mascot/app.rb
25
+ class RatatuiMascot < Data.define(:block)
26
+ include CoerceableWidget
27
+
28
+ ##
29
+ # :method: new
30
+ # :call-seq: new(block: nil) -> RatatuiMascot
31
+ #
32
+ # Creates a new RatatuiMascot.
33
+ #
34
+ # @param block [Block, nil] A block to wrap the widget in.
35
+ def initialize(block: nil)
36
+ super
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,123 @@
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 Widgets
10
+ # A styled table row combining cells with optional row-level styling.
11
+ #
12
+ # By default, Table rows are arrays of cell content. For more control over styling
13
+ # individual rows, wrap the cells in a Row object to apply row-level style.
14
+ #
15
+ # The cells can be Strings, Text::Spans, Text::Lines, Paragraphs, or Cells.
16
+ # The style applies to the entire row background.
17
+ #
18
+ # === Examples
19
+ #
20
+ #--
21
+ # SPDX-SnippetBegin
22
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
23
+ # SPDX-License-Identifier: MIT-0
24
+ #++
25
+ # # Row with red background
26
+ # Row.new(cells: ["Error", "Something went wrong"], style: Style.new(bg: :red))
27
+ #
28
+ # # Row with styled cells and custom height
29
+ # Row.new(
30
+ # cells: [
31
+ # Text::Span.new(content: "Status", style: Style.new(modifiers: [:bold])),
32
+ # Text::Span.new(content: "OK", style: Style.new(fg: :green))
33
+ # ],
34
+ # height: 2
35
+ # )
36
+ #--
37
+ # SPDX-SnippetEnd
38
+ #++
39
+ class Row < Data.define(:cells, :style, :height, :top_margin, :bottom_margin)
40
+ include CoerceableWidget
41
+
42
+ ##
43
+ # :attr_reader: cells
44
+ # The cells to display (Array of Strings, Text::Spans, Text::Lines, Paragraphs, or Cells).
45
+
46
+ ##
47
+ # :attr_reader: style
48
+ # The style to apply to the row (optional Style).
49
+
50
+ ##
51
+ # :attr_reader: height
52
+ # Fixed row height in lines (optional Integer).
53
+
54
+ ##
55
+ # :attr_reader: top_margin
56
+ # Margin above the row in lines (optional Integer).
57
+
58
+ ##
59
+ # :attr_reader: bottom_margin
60
+ # Margin below the row in lines (optional Integer).
61
+
62
+ # Creates a new Row.
63
+ #
64
+ # [cells] Array of Strings, Text::Spans, Text::Lines, Paragraphs, or Cells.
65
+ # [style] Style object (optional).
66
+ # [height] Integer for fixed height (optional).
67
+ # [top_margin] Integer for top margin (optional).
68
+ # [bottom_margin] Integer for bottom margin (optional).
69
+ def initialize(cells:, style: nil, height: nil, top_margin: nil, bottom_margin: nil)
70
+ super(
71
+ cells:,
72
+ style:,
73
+ height: height.nil? ? nil : Integer(height),
74
+ top_margin: top_margin.nil? ? nil : Integer(top_margin),
75
+ bottom_margin: bottom_margin.nil? ? nil : Integer(bottom_margin)
76
+ )
77
+ end
78
+
79
+ # Returns a new Row with strikethrough styling enabled.
80
+ #
81
+ # Table rows sometimes need strikethrough styling to indicate
82
+ # deleted, deprecated, or cancelled items. Manually managing
83
+ # style modifiers is tedious.
84
+ #
85
+ # This method adds the <tt>:crossed_out</tt> modifier to the row's
86
+ # style. If the row has no existing style, a new style is created.
87
+ #
88
+ # Use it to visually mark rows as cancelled, completed, or invalid.
89
+ #
90
+ # *Terminal Compatibility:* Strikethrough (SGR 9) is not universally
91
+ # supported. macOS Terminal.app notably lacks support. Modern terminals
92
+ # like Kitty, iTerm2, Alacritty, and WezTerm render it correctly.
93
+ # Consider pairing with <tt>:dim</tt> as a fallback for visibility.
94
+ #
95
+ # Returns a new Row instance with strikethrough enabled.
96
+ #
97
+ # === Example
98
+ #
99
+ #--
100
+ # SPDX-SnippetBegin
101
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
102
+ # SPDX-License-Identifier: MIT-0
103
+ #++
104
+ # row = Row.new(cells: ["Cancelled Task", "2024-01-15"])
105
+ # strikethrough_row = row.enable_strikethrough
106
+ # # Row style now includes :crossed_out modifier
107
+ #--
108
+ # SPDX-SnippetEnd
109
+ #++
110
+ def enable_strikethrough
111
+ current_style = style || Style::Style.new
112
+ current_modifiers = current_style.modifiers || []
113
+ new_modifiers = current_modifiers.include?(:crossed_out) ? current_modifiers : current_modifiers + [:crossed_out]
114
+
115
+ new_style = current_style.with(modifiers: new_modifiers)
116
+ with(style: new_style)
117
+ end
118
+
119
+ # Ruby-idiomatic alias
120
+ alias strikethrough enable_strikethrough
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,147 @@
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 Widgets
10
+ # Visualizes the scroll state of a viewport.
11
+ #
12
+ # Content overflows. Users get lost in long lists without landmarks. They need to know where they are and how much is left.
13
+ #
14
+ # This widget maps your context. It draws a track and a thumb, representing your current position relative to the total length.
15
+ #
16
+ # Overlay it on top of lists, paragraphs, or tables to provide spatial awareness.
17
+ #
18
+ # {rdoc-image:/doc/images/widget_scrollbar.png}[link:/examples/widget_scrollbar/app_rb.html]
19
+ #
20
+ # === Example
21
+ #
22
+ # Run the interactive demo from the terminal:
23
+ #
24
+ # ruby examples/widget_scrollbar/app.rb
25
+ class Scrollbar < Data.define(
26
+ :content_length,
27
+ :position,
28
+ :orientation,
29
+ :thumb_symbol,
30
+ :thumb_style,
31
+ :track_symbol,
32
+ :track_style,
33
+ :begin_symbol,
34
+ :begin_style,
35
+ :end_symbol,
36
+ :end_style,
37
+ :style,
38
+ :block
39
+ )
40
+ include CoerceableWidget
41
+
42
+ ##
43
+ # :attr_reader: content_length
44
+ # Total items or lines in the content.
45
+
46
+ ##
47
+ # :attr_reader: position
48
+ # Current scroll offset (index).
49
+ #
50
+ # Maps to Ratatui's <tt>ScrollbarState::get_position()</tt> (new in 0.30.0).
51
+
52
+ ##
53
+ # :attr_reader: orientation
54
+ # Direction of the scrollbar.
55
+ #
56
+ # <tt>:vertical</tt> (default, alias for <tt>:vertical_right</tt>), <tt>:horizontal</tt> (alias for <tt>:horizontal_bottom</tt>),
57
+ # <tt>:vertical_left</tt>, <tt>:vertical_right</tt>, <tt>:horizontal_top</tt>, or <tt>:horizontal_bottom</tt>.
58
+
59
+ ##
60
+ # :attr_reader: thumb_symbol
61
+ # Symbol used to represent the current position indicator.
62
+
63
+ ##
64
+ # :attr_reader: thumb_style
65
+ # Style of the position indicator (thumb).
66
+
67
+ ##
68
+ # :attr_reader: track_symbol
69
+ # Symbol used to represent the empty space of the scrollbar.
70
+
71
+ ##
72
+ # :attr_reader: track_style
73
+ # Style of the filled track area.
74
+
75
+ ##
76
+ # :attr_reader: begin_symbol
77
+ # Symbol rendered at the start of the track (e.g., arrow).
78
+
79
+ ##
80
+ # :attr_reader: begin_style
81
+ # Style of the start symbol.
82
+
83
+ ##
84
+ # :attr_reader: end_symbol
85
+ # Symbol rendered at the end of the track (e.g., arrow).
86
+
87
+ ##
88
+ # :attr_reader: end_style
89
+ # Style of the end symbol.
90
+
91
+ ##
92
+ # :attr_reader: style
93
+ # Base style applied to the entire widget.
94
+
95
+ ##
96
+ # :attr_reader: block
97
+ # Optional wrapping block.
98
+
99
+ # Creates a new Scrollbar.
100
+ #
101
+ # [content_length] Integer.
102
+ # [position] Integer.
103
+ # [orientation] Symbol (default: <tt>:vertical</tt>).
104
+ # [thumb_symbol] String (default: <tt>"█"</tt>).
105
+ # [thumb_style] Style (optional).
106
+ # [track_symbol] String (optional).
107
+ # [track_style] Style (optional).
108
+ # [begin_symbol] String (optional).
109
+ # [begin_style] Style (optional).
110
+ # [end_symbol] String (optional).
111
+ # [end_style] Style (optional).
112
+ # [style] Style (optional).
113
+ # [block] Block (optional).
114
+ def initialize(
115
+ content_length:,
116
+ position:,
117
+ orientation: :vertical,
118
+ thumb_symbol: "█",
119
+ thumb_style: nil,
120
+ track_symbol: nil,
121
+ track_style: nil,
122
+ begin_symbol: nil,
123
+ begin_style: nil,
124
+ end_symbol: nil,
125
+ end_style: nil,
126
+ style: nil,
127
+ block: nil
128
+ )
129
+ super(
130
+ content_length: Integer(content_length),
131
+ position: Integer(position),
132
+ orientation:,
133
+ thumb_symbol:,
134
+ thumb_style:,
135
+ track_symbol:,
136
+ track_style:,
137
+ begin_symbol:,
138
+ begin_style:,
139
+ end_symbol:,
140
+ end_style:,
141
+ style:,
142
+ block:
143
+ )
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,80 @@
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 Widgets
10
+ module Shape
11
+ # A text label on a canvas.
12
+ #
13
+ # Labels render text at specific coordinates in canvas space.
14
+ # Unlike shapes, labels are always rendered on top of all other canvas elements.
15
+ #
16
+ # [x] The x-coordinate in canvas space (Numeric).
17
+ # [y] The y-coordinate in canvas space (Numeric).
18
+ # [text] The text content (String or Text::Line).
19
+ # [style] Optional style for the text.
20
+ #
21
+ # === Examples
22
+ #
23
+ #--
24
+ # SPDX-SnippetBegin
25
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
26
+ # SPDX-License-Identifier: MIT-0
27
+ #++
28
+ # # Simple label
29
+ # Shape::Label.new(x: 0, y: 0, text: "Origin")
30
+ #
31
+ # # Styled label
32
+ # Shape::Label.new(
33
+ # x: -122.4, y: 37.8,
34
+ # text: "San Francisco",
35
+ # style: Style.new(fg: :cyan, add_modifier: :bold)
36
+ # )
37
+ #
38
+ # # Label with Text::Line for rich formatting
39
+ # Shape::Label.new(
40
+ # x: 0.0, y: 0.0,
41
+ # text: Text::Line.new(spans: [
42
+ # Text::Span.new(content: "Hello ", style: Style.new(fg: :red)),
43
+ # Text::Span.new(content: "World", style: Style.new(fg: :blue))
44
+ # ])
45
+ # )
46
+ #--
47
+ # SPDX-SnippetEnd
48
+ #++
49
+ class Label < Data.define(:x, :y, :text, :style)
50
+ include CoerceableWidget
51
+
52
+ ##
53
+ # :attr_reader: x
54
+ # X coordinate in canvas space (Float, duck-typed via +to_f+).
55
+
56
+ ##
57
+ # :attr_reader: y
58
+ # Y coordinate in canvas space (Float, duck-typed via +to_f+).
59
+
60
+ ##
61
+ # :attr_reader: text
62
+ # Text content (String or Text::Line).
63
+
64
+ ##
65
+ # :attr_reader: style
66
+ # Optional style for the text.
67
+
68
+ # Creates a new Label.
69
+ #
70
+ # [x] X coordinate (Numeric).
71
+ # [y] Y coordinate (Numeric).
72
+ # [text] Text content (String or Text::Line).
73
+ # [style] Style (optional).
74
+ def initialize(x:, y:, text:, style: nil)
75
+ super(x: Float(x), y: Float(y), text:, style:)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end