ratatui_ruby 0.9.0 → 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 (268) 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 +122 -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 +16 -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 +16 -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/sync.rb +52 -0
  85. data/lib/ratatui_ruby/event.rb +7 -1
  86. data/lib/ratatui_ruby/layout/constraint.rb +184 -0
  87. data/lib/ratatui_ruby/layout/layout.rb +119 -13
  88. data/lib/ratatui_ruby/layout/position.rb +55 -0
  89. data/lib/ratatui_ruby/layout/rect.rb +188 -0
  90. data/lib/ratatui_ruby/layout/size.rb +55 -0
  91. data/lib/ratatui_ruby/layout.rb +4 -0
  92. data/lib/ratatui_ruby/style/color.rb +149 -0
  93. data/lib/ratatui_ruby/style/style.rb +51 -4
  94. data/lib/ratatui_ruby/style.rb +2 -0
  95. data/lib/ratatui_ruby/symbols.rb +435 -0
  96. data/lib/ratatui_ruby/synthetic_events.rb +86 -0
  97. data/lib/ratatui_ruby/table_state.rb +51 -0
  98. data/lib/ratatui_ruby/terminal_lifecycle.rb +2 -1
  99. data/lib/ratatui_ruby/test_helper/event_injection.rb +34 -1
  100. data/lib/ratatui_ruby/test_helper.rb +9 -0
  101. data/lib/ratatui_ruby/text/line.rb +245 -0
  102. data/lib/ratatui_ruby/text/span.rb +158 -0
  103. data/lib/ratatui_ruby/text.rb +99 -0
  104. data/lib/ratatui_ruby/tui/canvas_factories.rb +103 -0
  105. data/lib/ratatui_ruby/tui/core.rb +13 -2
  106. data/lib/ratatui_ruby/tui/layout_factories.rb +50 -3
  107. data/lib/ratatui_ruby/tui/state_factories.rb +42 -0
  108. data/lib/ratatui_ruby/tui/text_factories.rb +40 -0
  109. data/lib/ratatui_ruby/tui/widget_factories.rb +135 -60
  110. data/lib/ratatui_ruby/tui.rb +22 -1
  111. data/lib/ratatui_ruby/version.rb +1 -1
  112. data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -0
  113. data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -0
  114. data/lib/ratatui_ruby/widgets/bar_chart.rb +30 -20
  115. data/lib/ratatui_ruby/widgets/block.rb +14 -6
  116. data/lib/ratatui_ruby/widgets/calendar.rb +2 -0
  117. data/lib/ratatui_ruby/widgets/canvas.rb +56 -0
  118. data/lib/ratatui_ruby/widgets/cell.rb +2 -0
  119. data/lib/ratatui_ruby/widgets/center.rb +2 -0
  120. data/lib/ratatui_ruby/widgets/chart.rb +6 -0
  121. data/lib/ratatui_ruby/widgets/clear.rb +2 -0
  122. data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
  123. data/lib/ratatui_ruby/widgets/cursor.rb +2 -0
  124. data/lib/ratatui_ruby/widgets/gauge.rb +61 -3
  125. data/lib/ratatui_ruby/widgets/line_gauge.rb +66 -4
  126. data/lib/ratatui_ruby/widgets/list.rb +87 -3
  127. data/lib/ratatui_ruby/widgets/list_item.rb +2 -0
  128. data/lib/ratatui_ruby/widgets/overlay.rb +2 -0
  129. data/lib/ratatui_ruby/widgets/paragraph.rb +4 -0
  130. data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -0
  131. data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -0
  132. data/lib/ratatui_ruby/widgets/row.rb +45 -0
  133. data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -0
  134. data/lib/ratatui_ruby/widgets/shape/label.rb +2 -0
  135. data/lib/ratatui_ruby/widgets/sparkline.rb +21 -13
  136. data/lib/ratatui_ruby/widgets/table.rb +13 -3
  137. data/lib/ratatui_ruby/widgets/tabs.rb +6 -4
  138. data/lib/ratatui_ruby/widgets.rb +1 -0
  139. data/lib/ratatui_ruby.rb +51 -16
  140. data/sig/examples/app_all_events/model/app_model.rbs +23 -0
  141. data/sig/examples/app_all_events/model/event_entry.rbs +15 -8
  142. data/sig/examples/app_all_events/model/timestamp.rbs +1 -1
  143. data/sig/examples/app_all_events/view.rbs +1 -1
  144. data/sig/examples/app_stateful_interaction/app.rbs +5 -5
  145. data/sig/examples/widget_block_demo/app.rbs +6 -6
  146. data/sig/manifest.yaml +5 -0
  147. data/sig/patches/data.rbs +26 -0
  148. data/sig/patches/debugger__.rbs +8 -0
  149. data/sig/ratatui_ruby/buffer/cell.rbs +46 -0
  150. data/sig/ratatui_ruby/buffer.rbs +18 -0
  151. data/sig/ratatui_ruby/cell.rbs +44 -0
  152. data/sig/ratatui_ruby/clear.rbs +18 -0
  153. data/sig/ratatui_ruby/constraint.rbs +26 -0
  154. data/sig/ratatui_ruby/debug.rbs +45 -0
  155. data/sig/ratatui_ruby/draw.rbs +30 -0
  156. data/sig/ratatui_ruby/event.rbs +68 -8
  157. data/sig/ratatui_ruby/frame.rbs +4 -4
  158. data/sig/ratatui_ruby/interfaces.rbs +25 -0
  159. data/sig/ratatui_ruby/layout/constraint.rbs +39 -0
  160. data/sig/ratatui_ruby/layout/layout.rbs +45 -0
  161. data/sig/ratatui_ruby/layout/position.rbs +18 -0
  162. data/sig/ratatui_ruby/layout/rect.rbs +64 -0
  163. data/sig/ratatui_ruby/layout/size.rbs +18 -0
  164. data/sig/ratatui_ruby/output_guard.rbs +23 -0
  165. data/sig/ratatui_ruby/ratatui_ruby.rbs +83 -4
  166. data/sig/ratatui_ruby/rect.rbs +17 -0
  167. data/sig/ratatui_ruby/style/color.rbs +22 -0
  168. data/sig/ratatui_ruby/style/style.rbs +29 -0
  169. data/sig/ratatui_ruby/symbols.rbs +141 -0
  170. data/sig/ratatui_ruby/synthetic_events.rbs +21 -0
  171. data/sig/ratatui_ruby/table_state.rbs +6 -0
  172. data/sig/ratatui_ruby/terminal_lifecycle.rbs +31 -0
  173. data/sig/ratatui_ruby/test_helper/event_injection.rbs +2 -2
  174. data/sig/ratatui_ruby/test_helper/snapshot.rbs +22 -3
  175. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +8 -1
  176. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -3
  177. data/sig/ratatui_ruby/text/line.rbs +27 -0
  178. data/sig/ratatui_ruby/text/span.rbs +23 -0
  179. data/sig/ratatui_ruby/text.rbs +12 -0
  180. data/sig/ratatui_ruby/tui/buffer_factories.rbs +1 -1
  181. data/sig/ratatui_ruby/tui/canvas_factories.rbs +23 -5
  182. data/sig/ratatui_ruby/tui/core.rbs +2 -2
  183. data/sig/ratatui_ruby/tui/layout_factories.rbs +16 -2
  184. data/sig/ratatui_ruby/tui/state_factories.rbs +8 -3
  185. data/sig/ratatui_ruby/tui/style_factories.rbs +3 -1
  186. data/sig/ratatui_ruby/tui/text_factories.rbs +7 -4
  187. data/sig/ratatui_ruby/tui/widget_factories.rbs +123 -30
  188. data/sig/ratatui_ruby/widgets/bar_chart.rbs +95 -0
  189. data/sig/ratatui_ruby/widgets/block.rbs +51 -0
  190. data/sig/ratatui_ruby/widgets/calendar.rbs +45 -0
  191. data/sig/ratatui_ruby/widgets/canvas.rbs +95 -0
  192. data/sig/ratatui_ruby/widgets/chart.rbs +91 -0
  193. data/sig/ratatui_ruby/widgets/coerceable_widget.rbs +26 -0
  194. data/sig/ratatui_ruby/widgets/gauge.rbs +44 -0
  195. data/sig/ratatui_ruby/widgets/line_gauge.rbs +48 -0
  196. data/sig/ratatui_ruby/widgets/list.rbs +63 -0
  197. data/sig/ratatui_ruby/widgets/misc.rbs +158 -0
  198. data/sig/ratatui_ruby/widgets/paragraph.rbs +45 -0
  199. data/sig/ratatui_ruby/widgets/row.rbs +43 -0
  200. data/sig/ratatui_ruby/widgets/scrollbar.rbs +53 -0
  201. data/sig/ratatui_ruby/widgets/shape/label.rbs +37 -0
  202. data/sig/ratatui_ruby/widgets/sparkline.rbs +45 -0
  203. data/sig/ratatui_ruby/widgets/table.rbs +78 -0
  204. data/sig/ratatui_ruby/widgets/tabs.rbs +44 -0
  205. data/sig/ratatui_ruby/{schema/list_item.rbs → widgets.rbs} +4 -4
  206. data/tasks/steep.rake +11 -0
  207. metadata +82 -63
  208. data/doc/contributors/v1.0.0_blockers.md +0 -876
  209. data/doc/troubleshooting/debugging.md +0 -101
  210. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +0 -47
  211. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +0 -25
  212. data/lib/ratatui_ruby/schema/bar_chart.rb +0 -287
  213. data/lib/ratatui_ruby/schema/block.rb +0 -198
  214. data/lib/ratatui_ruby/schema/calendar.rb +0 -84
  215. data/lib/ratatui_ruby/schema/canvas.rb +0 -239
  216. data/lib/ratatui_ruby/schema/center.rb +0 -67
  217. data/lib/ratatui_ruby/schema/chart.rb +0 -159
  218. data/lib/ratatui_ruby/schema/clear.rb +0 -62
  219. data/lib/ratatui_ruby/schema/constraint.rb +0 -151
  220. data/lib/ratatui_ruby/schema/cursor.rb +0 -50
  221. data/lib/ratatui_ruby/schema/gauge.rb +0 -72
  222. data/lib/ratatui_ruby/schema/layout.rb +0 -122
  223. data/lib/ratatui_ruby/schema/line_gauge.rb +0 -80
  224. data/lib/ratatui_ruby/schema/list.rb +0 -135
  225. data/lib/ratatui_ruby/schema/list_item.rb +0 -51
  226. data/lib/ratatui_ruby/schema/overlay.rb +0 -51
  227. data/lib/ratatui_ruby/schema/paragraph.rb +0 -107
  228. data/lib/ratatui_ruby/schema/ratatui_logo.rb +0 -31
  229. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +0 -36
  230. data/lib/ratatui_ruby/schema/rect.rb +0 -174
  231. data/lib/ratatui_ruby/schema/row.rb +0 -76
  232. data/lib/ratatui_ruby/schema/scrollbar.rb +0 -143
  233. data/lib/ratatui_ruby/schema/shape/label.rb +0 -76
  234. data/lib/ratatui_ruby/schema/sparkline.rb +0 -142
  235. data/lib/ratatui_ruby/schema/style.rb +0 -97
  236. data/lib/ratatui_ruby/schema/table.rb +0 -141
  237. data/lib/ratatui_ruby/schema/tabs.rb +0 -85
  238. data/lib/ratatui_ruby/schema/text.rb +0 -217
  239. data/sig/examples/app_all_events/model/events.rbs +0 -15
  240. data/sig/examples/app_all_events/view_state.rbs +0 -21
  241. data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +0 -22
  242. data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +0 -19
  243. data/sig/ratatui_ruby/schema/bar_chart.rbs +0 -38
  244. data/sig/ratatui_ruby/schema/block.rbs +0 -18
  245. data/sig/ratatui_ruby/schema/calendar.rbs +0 -23
  246. data/sig/ratatui_ruby/schema/canvas.rbs +0 -81
  247. data/sig/ratatui_ruby/schema/center.rbs +0 -17
  248. data/sig/ratatui_ruby/schema/chart.rbs +0 -39
  249. data/sig/ratatui_ruby/schema/constraint.rbs +0 -22
  250. data/sig/ratatui_ruby/schema/cursor.rbs +0 -16
  251. data/sig/ratatui_ruby/schema/draw.rbs +0 -33
  252. data/sig/ratatui_ruby/schema/gauge.rbs +0 -23
  253. data/sig/ratatui_ruby/schema/layout.rbs +0 -27
  254. data/sig/ratatui_ruby/schema/line_gauge.rbs +0 -24
  255. data/sig/ratatui_ruby/schema/list.rbs +0 -28
  256. data/sig/ratatui_ruby/schema/overlay.rbs +0 -15
  257. data/sig/ratatui_ruby/schema/paragraph.rbs +0 -20
  258. data/sig/ratatui_ruby/schema/ratatui_logo.rbs +0 -14
  259. data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +0 -17
  260. data/sig/ratatui_ruby/schema/rect.rbs +0 -48
  261. data/sig/ratatui_ruby/schema/row.rbs +0 -28
  262. data/sig/ratatui_ruby/schema/scrollbar.rbs +0 -42
  263. data/sig/ratatui_ruby/schema/sparkline.rbs +0 -22
  264. data/sig/ratatui_ruby/schema/style.rbs +0 -19
  265. data/sig/ratatui_ruby/schema/table.rbs +0 -32
  266. data/sig/ratatui_ruby/schema/tabs.rbs +0 -21
  267. data/sig/ratatui_ruby/schema/text.rbs +0 -31
  268. /data/lib/ratatui_ruby/{schema/draw.rb → draw.rb} +0 -0
@@ -1,84 +0,0 @@
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
- # Displays a monthly calendar grid.
10
- #
11
- # Dates are complex. Rendering them in a grid requires calculation of leap years, month lengths, and day-of-week offsets.
12
- # Use this widget to skip the boilerplate.
13
- #
14
- # This widget renders a standard monthly view. It highlights the current date. It structures time.
15
- #
16
- # Use it for date pickers, schedulers, or logs.
17
- #
18
- # {rdoc-image:/doc/images/widget_calendar.png}[link:/examples/widget_calendar/app_rb.html]
19
- #
20
- # === Example
21
- #
22
- # Run the interactive demo from the terminal:
23
- #
24
- # ruby examples/widget_calendar/app.rb
25
- class Calendar < Data.define(:year, :month, :events, :default_style, :header_style, :block, :show_weekdays_header, :show_surrounding, :show_month_header)
26
- ##
27
- # :attr_reader: year
28
- # The year to display (Integer).
29
-
30
- ##
31
- # :attr_reader: month
32
- # The month to display (1–12).
33
-
34
- ##
35
- # :attr_reader: events
36
- # A Hash mapping Dates to Styles for event highlighting.
37
- # Keys must be `Date` objects (or objects responding to `day`, `month`, `year`).
38
- # Values must be `Style` objects.
39
-
40
- ##
41
- # :attr_reader: default_style
42
- # Style for the days.
43
-
44
- ##
45
- # :attr_reader: header_style
46
- # Style for the month name header.
47
-
48
- ##
49
- # :attr_reader: block
50
- # Optional wrapping block.
51
-
52
- ##
53
- # :attr_reader: show_weekdays_header
54
- # Whether to show the weekday header (Mon, Tue, etc.).
55
-
56
- ##
57
- # :attr_reader: show_surrounding
58
- # Style for dates from surrounding months. If <tt>nil</tt>, surrounding dates are hidden.
59
-
60
- # Creates a new Calendar.
61
- #
62
- # [year] Integer.
63
- # [month] Integer.
64
- # [events] Hash<Date, Style>. Optional.
65
- # [default_style] Style.
66
- # [header_style] Style.
67
- # [block] Block.
68
- # [show_weekdays_header] Boolean. Whether to show the weekday header.
69
- # [show_surrounding] <tt>Style</tt> or <tt>nil</tt>. Style for surrounding month dates.
70
- def initialize(year:, month:, events: {}, default_style: nil, header_style: nil, block: nil, show_weekdays_header: true, show_surrounding: nil, show_month_header: false)
71
- super(
72
- year: Integer(year),
73
- month: Integer(month),
74
- events:,
75
- default_style:,
76
- header_style:,
77
- block:,
78
- show_weekdays_header:,
79
- show_surrounding:,
80
- show_month_header:
81
- )
82
- end
83
- end
84
- end
@@ -1,239 +0,0 @@
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
- # Namespace for canvas shape primitives (Point, Line, Rectangle, Circle, Map, Label).
10
- # Distinct from text components and other Line usages.
11
- module Shape
12
- # A point in the canvas coordinate system.
13
- #
14
- # [x] The x-coordinate.
15
- # [y] The y-coordinate.
16
- class Point < Data.define(:x, :y)
17
- ##
18
- # :attr_reader: x
19
- # X coordinate (Float, duck-typed via +to_f+).
20
-
21
- ##
22
- # :attr_reader: y
23
- # Y coordinate (Float, duck-typed via +to_f+).
24
-
25
- # Creates a new Point.
26
- #
27
- # [x] X coordinate (Numeric).
28
- # [y] Y coordinate (Numeric).
29
- def initialize(x:, y:)
30
- super(x: Float(x), y: Float(y))
31
- end
32
- end
33
-
34
- # A line shape on a canvas.
35
- #
36
- # [x1] The starting x-coordinate.
37
- # [y1] The starting y-coordinate.
38
- # [x2] The ending x-coordinate.
39
- # [y2] The ending y-coordinate.
40
- # [color] The color of the line.
41
- class Line < Data.define(:x1, :y1, :x2, :y2, :color)
42
- ##
43
- # :attr_reader: x1
44
- # Start X (Float, duck-typed via +to_f+).
45
-
46
- ##
47
- # :attr_reader: y1
48
- # Start Y (Float, duck-typed via +to_f+).
49
-
50
- ##
51
- # :attr_reader: x2
52
- # End X (Float, duck-typed via +to_f+).
53
-
54
- ##
55
- # :attr_reader: y2
56
- # End Y (Float, duck-typed via +to_f+).
57
-
58
- ##
59
- # :attr_reader: color
60
- # Line color.
61
-
62
- # Creates a new Line.
63
- #
64
- # [x1] Start X (Numeric).
65
- # [y1] Start Y (Numeric).
66
- # [x2] End X (Numeric).
67
- # [y2] End Y (Numeric).
68
- # [color] Line color (Symbol).
69
- def initialize(x1:, y1:, x2:, y2:, color:)
70
- super(x1: Float(x1), y1: Float(y1), x2: Float(x2), y2: Float(y2), color:)
71
- end
72
- end
73
-
74
- # A rectangle shape on a canvas.
75
- #
76
- # [x] The x-coordinate of the bottom-left corner.
77
- # [y] The y-coordinate of the bottom-left corner.
78
- # [width] The width of the rectangle.
79
- # [height] The height of the rectangle.
80
- # [color] The color of the rectangle.
81
- class Rectangle < Data.define(:x, :y, :width, :height, :color)
82
- ##
83
- # :attr_reader: x
84
- # Bottom-left X (Float, duck-typed via +to_f+).
85
-
86
- ##
87
- # :attr_reader: y
88
- # Bottom-left Y (Float, duck-typed via +to_f+).
89
-
90
- ##
91
- # :attr_reader: width
92
- # Width (Float, duck-typed via +to_f+).
93
-
94
- ##
95
- # :attr_reader: height
96
- # Height (Float, duck-typed via +to_f+).
97
-
98
- ##
99
- # :attr_reader: color
100
- # Color.
101
-
102
- # Creates a new Rectangle.
103
- #
104
- # [x] Bottom-left X (Numeric).
105
- # [y] Bottom-left Y (Numeric).
106
- # [width] Width (Numeric).
107
- # [height] Height (Numeric).
108
- # [color] Color (Symbol).
109
- def initialize(x:, y:, width:, height:, color:)
110
- super(x: Float(x), y: Float(y), width: Float(width), height: Float(height), color:)
111
- end
112
- end
113
-
114
- # A circle shape on a canvas.
115
- #
116
- # [x] The x-coordinate of the center.
117
- # [y] The y-coordinate of the center.
118
- # [radius] The radius of the circle.
119
- # [color] The color of the circle.
120
- class Circle < Data.define(:x, :y, :radius, :color)
121
- ##
122
- # :attr_reader: x
123
- # Center X (Float, duck-typed via +to_f+).
124
-
125
- ##
126
- # :attr_reader: y
127
- # Center Y (Float, duck-typed via +to_f+).
128
-
129
- ##
130
- # :attr_reader: radius
131
- # Radius (Float, duck-typed via +to_f+).
132
-
133
- ##
134
- # :attr_reader: color
135
- # Color.
136
-
137
- # Creates a new Circle.
138
- #
139
- # [x] Center X (Numeric).
140
- # [y] Center Y (Numeric).
141
- # [radius] Radius (Numeric).
142
- # [color] Color (Symbol).
143
- def initialize(x:, y:, radius:, color:)
144
- super(x: Float(x), y: Float(y), radius: Float(radius), color:)
145
- end
146
- end
147
-
148
- # A world map shape on a canvas.
149
- #
150
- # [color] The color of the map.
151
- # [resolution] The resolution of the map (<tt>:low</tt>, <tt>:high</tt>).
152
- class Map < Data.define(:color, :resolution)
153
- ##
154
- # :attr_reader: color
155
- # Map color.
156
-
157
- ##
158
- # :attr_reader: resolution
159
- # Resolution (<tt>:low</tt> or <tt>:high</tt>).
160
- end
161
- end
162
-
163
- # Provides a drawing surface for custom shapes.
164
- #
165
- # Standard widgets cover standard cases. Sometimes you need to draw a map, a custom diagram, or a game.
166
- # Character grids are too coarse for fine detail.
167
- #
168
- # This widget increases the resolution. It uses Braille patterns or block characters to create a "sub-pixel" drawing surface.
169
- #
170
- # Use it to implement free-form graphics, high-resolution plots, or geographic maps.
171
- #
172
- # === Examples
173
- #
174
- #--
175
- # SPDX-SnippetBegin
176
- # SPDX-FileCopyrightText: 2025 Kerrick Long
177
- # SPDX-License-Identifier: MIT-0
178
- #++
179
- # Canvas.new(
180
- # x_bounds: [-180, 180],
181
- # y_bounds: [-90, 90],
182
- # shapes: [
183
- # Shape::Map.new(color: :green, resolution: :high),
184
- # Shape::Circle.new(x: 0, y: 0, radius: 10, color: :red),
185
- # Shape::Label.new(x: -122.4, y: 37.8, text: "San Francisco")
186
- # ]
187
- # )
188
- #--
189
- # SPDX-SnippetEnd
190
- #++
191
- class Canvas < Data.define(:shapes, :x_bounds, :y_bounds, :marker, :block, :background_color)
192
- ##
193
- # :attr_reader: shapes
194
- # Array of shapes to render.
195
- #
196
- # Includes {Shape::Line}, {Shape::Circle}, {Shape::Map}, etc.
197
-
198
- ##
199
- # :attr_reader: x_bounds
200
- # [min, max] range for the x-axis.
201
-
202
- ##
203
- # :attr_reader: y_bounds
204
- # [min, max] range for the y-axis.
205
-
206
- ##
207
- # :attr_reader: marker
208
- # The marker type used for drawing.
209
- #
210
- # <tt>:braille</tt> (high res), <tt>:half_block</tt>, <tt>:dot</tt>, <tt>:block</tt>, <tt>:bar</tt>.
211
-
212
- ##
213
- # :attr_reader: block
214
- # Optional wrapping block.
215
-
216
- ##
217
- # :attr_reader: background_color
218
- # The background color of the canvas.
219
-
220
- # Creates a new Canvas.
221
- #
222
- # [shapes] Array of Shapes.
223
- # [x_bounds] Array of [min, max] (Numeric, duck-typed via +to_f+).
224
- # [y_bounds] Array of [min, max] (Numeric, duck-typed via +to_f+).
225
- # [marker] Symbol (default: <tt>:braille</tt>).
226
- # [block] Block (optional).
227
- # [background_color] Color (optional).
228
- def initialize(shapes: [], x_bounds: [0.0, 100.0], y_bounds: [0.0, 100.0], marker: :braille, block: nil, background_color: nil)
229
- super(
230
- shapes:,
231
- x_bounds: [Float(x_bounds[0]), Float(x_bounds[1])],
232
- y_bounds: [Float(y_bounds[0]), Float(y_bounds[1])],
233
- marker:,
234
- block:,
235
- background_color:
236
- )
237
- end
238
- end
239
- end
@@ -1,67 +0,0 @@
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
- # Centers content within available space.
10
- #
11
- # Layouts often require alignment. Manually calculating offsets for centering is error-prone and brittle.
12
- #
13
- # This widget handles the math. It centers a child widget within the current area, resizing the child
14
- # according to optional percentage modifiers.
15
- #
16
- # Use it to position modals, splash screens, or floating dialogue boxes.
17
- #
18
- # === Examples
19
- #
20
- #--
21
- # SPDX-SnippetBegin
22
- # SPDX-FileCopyrightText: 2025 Kerrick Long
23
- # SPDX-License-Identifier: MIT-0
24
- #++
25
- # # Center a paragraph using 50% of width and height
26
- # Center.new(
27
- # child: Paragraph.new(text: "Hello"),
28
- # width_percent: 50,
29
- # height_percent: 50
30
- # )
31
- #--
32
- # SPDX-SnippetEnd
33
- #++
34
- class Center < Data.define(:child, :width_percent, :height_percent)
35
- ##
36
- # :attr_reader: child
37
- # The widget to be centered.
38
-
39
- ##
40
- # :attr_reader: width_percent
41
- # Width of the centered area as a percentage (0-100).
42
- #
43
- # If 50, the child occupies half the available width.
44
-
45
- ##
46
- # :attr_reader: height_percent
47
- # Height of the centered area as a percentage (0-100).
48
- #
49
- # If 50, the child occupies half the available height.
50
-
51
- # Creates a new Center widget.
52
- #
53
- # [child]
54
- # Widget to render.
55
- # [width_percent]
56
- # Target width percentage (Integer, default: 100).
57
- # [height_percent]
58
- # Target height percentage (Integer, default: 100).
59
- def initialize(child:, width_percent: 100, height_percent: 100)
60
- super(
61
- child:,
62
- width_percent: Float(width_percent),
63
- height_percent: Float(height_percent)
64
- )
65
- end
66
- end
67
- end
@@ -1,159 +0,0 @@
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
- # Defines an Axis for a Chart
10
- # [title] String
11
- # [bounds] Array<Float> [min, max]
12
- # [labels] Array<String>
13
- # [style] Style
14
- # [labels_alignment] Symbol (<tt>:left</tt>, <tt>:center</tt>, <tt>:right</tt>)
15
- class Axis < Data.define(:title, :bounds, :labels, :style, :labels_alignment)
16
- ##
17
- # :attr_reader: title
18
- # Label for the axis (String).
19
-
20
- ##
21
- # :attr_reader: bounds
22
- # Range [min, max] (Array of Floats).
23
-
24
- ##
25
- # :attr_reader: labels
26
- # Explicit labels for ticks (Array of Strings).
27
-
28
- ##
29
- # :attr_reader: style
30
- # Style for axis lines/text.
31
-
32
- ##
33
- # :attr_reader: labels_alignment
34
- # Alignment of axis labels (:left, :center, :right).
35
-
36
- # Creates a new Axis.
37
- #
38
- # [title] String.
39
- # [bounds] Array [min, max].
40
- # [labels] Array of Strings.
41
- # [style] Style.
42
- # [labels_alignment] Symbol (:left, :center, :right).
43
- def initialize(title: "", bounds: [0.0, 10.0], labels: [], style: nil, labels_alignment: nil)
44
- super(
45
- title:,
46
- bounds: [Float(bounds[0]), Float(bounds[1])],
47
- labels:,
48
- style:,
49
- labels_alignment:
50
- )
51
- end
52
- end
53
-
54
- # Defines a Dataset for a Chart.
55
- # [name] The name of the dataset.
56
- # [data] Array of arrays [[x, y], [x, y]] (Floats).
57
- # [style] The style of the line.
58
- # [marker] Symbol (<tt>:dot</tt>, <tt>:braille</tt>, <tt>:block</tt>, <tt>:bar</tt>)
59
- # [graph_type] Symbol (<tt>:line</tt>, <tt>:scatter</tt>)
60
- class Dataset < Data.define(:name, :data, :style, :marker, :graph_type)
61
- ##
62
- # :attr_reader: name
63
- # Name for logical identification or legend.
64
-
65
- ##
66
- # :attr_reader: data
67
- # list of [x, y] coordinates.
68
-
69
- ##
70
- # :attr_reader: style
71
- # Style applied to the dataset (Style).
72
- #
73
- # **Note**: Due to Ratatui's Chart widget design, only the foreground color (<tt>fg</tt>) is applied to markers in the chart area.
74
- # The full style (including <tt>bg</tt> and <tt>modifiers</tt>) is displayed in the legend.
75
- #
76
- # Supports:
77
- # - +fg+: Foreground color of markers (Symbol/Hex) - _applied to chart_
78
- # - +bg+: Background color (Symbol/Hex) - _legend only_
79
- # - +modifiers+: Array of effects (<tt>:bold</tt>, <tt>:dim</tt>, <tt>:italic</tt>, <tt>:underlined</tt>, <tt>:slow_blink</tt>, <tt>:rapid_blink</tt>, <tt>:reversed</tt>, <tt>:hidden</tt>, <tt>:crossed_out</tt>) - _legend only_
80
-
81
- ##
82
- # :attr_reader: marker
83
- # Marker type (<tt>:dot</tt>, <tt>:braille</tt>).
84
-
85
- ##
86
- # :attr_reader: graph_type
87
- # Type of graph (<tt>:line</tt>, <tt>:scatter</tt>).
88
-
89
- # Creates a new Dataset.
90
- #
91
- # [name] String.
92
- # [data] Array of [x, y] (Numeric, duck-typed via +to_f+).
93
- # [style] Style.
94
- # [marker] Symbol.
95
- # [graph_type] Symbol.
96
- def initialize(name:, data:, style: nil, marker: :dot, graph_type: :line)
97
- coerced_data = data.map { |point| [Float(point[0]), Float(point[1])] }
98
- super(name:, data: coerced_data, style:, marker:, graph_type:)
99
- end
100
- end
101
-
102
- # Plots data points on a Cartesian coordinate system.
103
- #
104
- # Trends and patterns are invisible in raw logs. You need to see the shape of the data to understand the story it tells.
105
- #
106
- # This widget plots X/Y coordinates. It supports multiple datasets, custom axes, and different marker types.
107
- #
108
- # Use it for analytics, scientific data, or monitoring metrics over time.
109
- #
110
- # {rdoc-image:/doc/images/widget_chart.png}[link:/examples/widget_chart/app_rb.html]
111
- #
112
- # === Example
113
- #
114
- # Run the interactive demo from the terminal:
115
- #
116
- # ruby examples/widget_chart/app.rb
117
- class Chart < Data.define(:datasets, :x_axis, :y_axis, :block, :style, :legend_position, :hidden_legend_constraints)
118
- ##
119
- # :attr_reader: datasets
120
- # Array of Dataset objects to plot.
121
-
122
- ##
123
- # :attr_reader: x_axis
124
- # Configuration for the X Axis.
125
-
126
- ##
127
- # :attr_reader: y_axis
128
- # Configuration for the Y Axis.
129
-
130
- ##
131
- # :attr_reader: block
132
- # Optional wrapping block.
133
-
134
- ##
135
- # :attr_reader: style
136
- # Base style for the chart area.
137
-
138
- ##
139
- # :attr_reader: legend_position
140
- # Position of the legend (<tt>:top_left</tt>, <tt>:top_right</tt>, <tt>:bottom_left</tt>, <tt>:bottom_right</tt>).
141
-
142
- ##
143
- # :attr_reader: hidden_legend_constraints
144
- # Constraints for hiding the legend when the chart is too small (Array of [width, height]).
145
-
146
- # Creates a new Chart widget.
147
- #
148
- # [datasets] Array of Datasets.
149
- # [x_axis] X Axis config.
150
- # [y_axis] Y Axis config.
151
- # [block] Wrapper (optional).
152
- # [style] Base style (optional).
153
- # [legend_position] Symbol (<tt>:top_left</tt>, <tt>:top_right</tt>, <tt>:bottom_left</tt>, <tt>:bottom_right</tt>).
154
- # [hidden_legend_constraints] Array of two Constraints [width, height] (optional).
155
- def initialize(datasets:, x_axis:, y_axis:, block: nil, style: nil, legend_position: nil, hidden_legend_constraints: [])
156
- super
157
- end
158
- end
159
- end
@@ -1,62 +0,0 @@
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
- # Resets the terminal buffer for a specific area.
10
- #
11
- # Painting in a terminal is additive. New content draws over old content. If the new content has transparency
12
- # or empty spaces, the old content "bleeds" through. This ruins popups and modals.
13
- #
14
- # This widget wipes the slate clean. It resets all cells in its area to their default state (spaces with default background).
15
- #
16
- # Use it as the first layer in an Overlay stack when building popups. Ensure your floating windows are truly opaque.
17
- #
18
- # === Examples
19
- #
20
- #--
21
- # SPDX-SnippetBegin
22
- # SPDX-FileCopyrightText: 2025 Kerrick Long
23
- # SPDX-License-Identifier: MIT-0
24
- #++
25
- # # Opaque Popup Construction
26
- # Overlay.new(
27
- # layers: [
28
- # MainUI.new,
29
- # Center.new(
30
- # child: Overlay.new(
31
- # layers: [
32
- # Clear.new, # Wipe the area first
33
- # Block.new(title: "Modal", borders: [:all])
34
- # ]
35
- # ),
36
- # width_percent: 50,
37
- # height_percent: 50
38
- # )
39
- # ]
40
- # )
41
- #
42
- # # Shortcut: rendering a block directly
43
- # Clear.new(block: Block.new(title: "Cleared area", borders: [:all]))
44
- #--
45
- # SPDX-SnippetEnd
46
- #++
47
- class Clear < Data.define(:block)
48
- ##
49
- # :attr_reader: block
50
- # Optional Block to render after clearing.
51
- #
52
- # If provided, the borders/title of this block are drawn on top of the cleared area.
53
-
54
- # Creates a new Clear widget.
55
- #
56
- # [block]
57
- # Block widget to render (optional).
58
- def initialize(block: nil)
59
- super
60
- end
61
- end
62
- end