ratatui_ruby 1.2.0 → 1.2.2

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 (260) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ratatui_ruby/Cargo.lock +2 -1
  3. data/ext/ratatui_ruby/Cargo.toml +2 -1
  4. data/ext/ratatui_ruby/src/events.rs +157 -18
  5. data/lib/ratatui_ruby/version.rb +1 -1
  6. metadata +1 -255
  7. data/.builds/ruby-3.2.yml +0 -54
  8. data/.builds/ruby-3.3.yml +0 -54
  9. data/.builds/ruby-3.4.yml +0 -54
  10. data/.builds/ruby-4.0.0.yml +0 -54
  11. data/.pre-commit-config.yaml +0 -16
  12. data/.rubocop.yml +0 -10
  13. data/AGENTS.md +0 -147
  14. data/CHANGELOG.md +0 -751
  15. data/README.md +0 -187
  16. data/README.rdoc +0 -302
  17. data/Rakefile +0 -11
  18. data/Steepfile +0 -50
  19. data/doc/concepts/application_architecture.md +0 -321
  20. data/doc/concepts/application_testing.md +0 -193
  21. data/doc/concepts/async.md +0 -190
  22. data/doc/concepts/custom_widgets.md +0 -247
  23. data/doc/concepts/debugging.md +0 -401
  24. data/doc/concepts/event_handling.md +0 -162
  25. data/doc/concepts/interactive_design.md +0 -146
  26. data/doc/contributors/auditing/parity.md +0 -239
  27. data/doc/contributors/design/ruby_frontend.md +0 -448
  28. data/doc/contributors/design/rust_backend.md +0 -434
  29. data/doc/contributors/design.md +0 -11
  30. data/doc/contributors/developing_examples.md +0 -400
  31. data/doc/contributors/documentation_style.md +0 -121
  32. data/doc/contributors/index.md +0 -21
  33. data/doc/contributors/releasing.md +0 -215
  34. data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -381
  35. data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -200
  36. data/doc/contributors/todo/align/term.md +0 -351
  37. data/doc/contributors/todo/align/terminal.md +0 -647
  38. data/doc/contributors/todo/future_work.md +0 -169
  39. data/doc/contributors/upstream_requests/paragraph_span_rects.md +0 -259
  40. data/doc/contributors/upstream_requests/tab_rects.md +0 -173
  41. data/doc/contributors/upstream_requests/title_rects.md +0 -132
  42. data/doc/custom.css +0 -22
  43. data/doc/getting_started/quickstart.md +0 -291
  44. data/doc/getting_started/why.md +0 -93
  45. data/doc/images/app_all_events.png +0 -0
  46. data/doc/images/app_cli_rich_moments.gif +0 -0
  47. data/doc/images/app_color_picker.png +0 -0
  48. data/doc/images/app_debugging_showcase.gif +0 -0
  49. data/doc/images/app_debugging_showcase.png +0 -0
  50. data/doc/images/app_external_editor.gif +0 -0
  51. data/doc/images/app_login_form.png +0 -0
  52. data/doc/images/app_stateful_interaction.png +0 -0
  53. data/doc/images/verify_quickstart_dsl.png +0 -0
  54. data/doc/images/verify_quickstart_layout.png +0 -0
  55. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  56. data/doc/images/verify_readme_usage.png +0 -0
  57. data/doc/images/widget_barchart.png +0 -0
  58. data/doc/images/widget_block.png +0 -0
  59. data/doc/images/widget_box.png +0 -0
  60. data/doc/images/widget_calendar.png +0 -0
  61. data/doc/images/widget_canvas.png +0 -0
  62. data/doc/images/widget_cell.png +0 -0
  63. data/doc/images/widget_center.png +0 -0
  64. data/doc/images/widget_chart.png +0 -0
  65. data/doc/images/widget_gauge.png +0 -0
  66. data/doc/images/widget_layout_split.png +0 -0
  67. data/doc/images/widget_line_gauge.png +0 -0
  68. data/doc/images/widget_list.png +0 -0
  69. data/doc/images/widget_map.png +0 -0
  70. data/doc/images/widget_overlay.png +0 -0
  71. data/doc/images/widget_popup.png +0 -0
  72. data/doc/images/widget_ratatui_logo.png +0 -0
  73. data/doc/images/widget_ratatui_mascot.png +0 -0
  74. data/doc/images/widget_rect.png +0 -0
  75. data/doc/images/widget_render.png +0 -0
  76. data/doc/images/widget_rich_text.png +0 -0
  77. data/doc/images/widget_scroll_text.png +0 -0
  78. data/doc/images/widget_scrollbar.png +0 -0
  79. data/doc/images/widget_sparkline.png +0 -0
  80. data/doc/images/widget_style_colors.png +0 -0
  81. data/doc/images/widget_table.png +0 -0
  82. data/doc/images/widget_tabs.png +0 -0
  83. data/doc/images/widget_text_width.png +0 -0
  84. data/doc/index.md +0 -34
  85. data/doc/troubleshooting/async.md +0 -4
  86. data/doc/troubleshooting/terminal_limitations.md +0 -131
  87. data/doc/troubleshooting/tui_output.md +0 -197
  88. data/examples/app_all_events/README.md +0 -114
  89. data/examples/app_all_events/app.rb +0 -98
  90. data/examples/app_all_events/model/app_model.rb +0 -159
  91. data/examples/app_all_events/model/event_color_cycle.rb +0 -43
  92. data/examples/app_all_events/model/event_entry.rb +0 -94
  93. data/examples/app_all_events/model/msg.rb +0 -39
  94. data/examples/app_all_events/model/timestamp.rb +0 -56
  95. data/examples/app_all_events/update.rb +0 -75
  96. data/examples/app_all_events/view/app_view.rb +0 -80
  97. data/examples/app_all_events/view/controls_view.rb +0 -54
  98. data/examples/app_all_events/view/counts_view.rb +0 -61
  99. data/examples/app_all_events/view/live_view.rb +0 -72
  100. data/examples/app_all_events/view/log_view.rb +0 -57
  101. data/examples/app_all_events/view.rb +0 -9
  102. data/examples/app_cli_rich_moments/README.md +0 -81
  103. data/examples/app_cli_rich_moments/app.rb +0 -189
  104. data/examples/app_color_picker/README.md +0 -156
  105. data/examples/app_color_picker/app.rb +0 -76
  106. data/examples/app_color_picker/clipboard.rb +0 -86
  107. data/examples/app_color_picker/color.rb +0 -193
  108. data/examples/app_color_picker/controls.rb +0 -92
  109. data/examples/app_color_picker/copy_dialog.rb +0 -168
  110. data/examples/app_color_picker/export_pane.rb +0 -128
  111. data/examples/app_color_picker/harmony.rb +0 -58
  112. data/examples/app_color_picker/input.rb +0 -176
  113. data/examples/app_color_picker/main_container.rb +0 -180
  114. data/examples/app_color_picker/palette.rb +0 -111
  115. data/examples/app_debugging_showcase/README.md +0 -119
  116. data/examples/app_debugging_showcase/app.rb +0 -318
  117. data/examples/app_external_editor/README.md +0 -62
  118. data/examples/app_external_editor/app.rb +0 -344
  119. data/examples/app_login_form/README.md +0 -58
  120. data/examples/app_login_form/app.rb +0 -109
  121. data/examples/app_stateful_interaction/README.md +0 -35
  122. data/examples/app_stateful_interaction/app.rb +0 -328
  123. data/examples/timeout_demo.rb +0 -45
  124. data/examples/verify_quickstart_dsl/README.md +0 -55
  125. data/examples/verify_quickstart_dsl/app.rb +0 -49
  126. data/examples/verify_quickstart_layout/README.md +0 -77
  127. data/examples/verify_quickstart_layout/app.rb +0 -73
  128. data/examples/verify_quickstart_lifecycle/README.md +0 -68
  129. data/examples/verify_quickstart_lifecycle/app.rb +0 -62
  130. data/examples/verify_readme_usage/README.md +0 -49
  131. data/examples/verify_readme_usage/app.rb +0 -42
  132. data/examples/verify_website_managed/README.md +0 -48
  133. data/examples/verify_website_managed/app.rb +0 -36
  134. data/examples/verify_website_menu/README.md +0 -60
  135. data/examples/verify_website_menu/app.rb +0 -84
  136. data/examples/verify_website_spinner/README.md +0 -44
  137. data/examples/verify_website_spinner/app.rb +0 -34
  138. data/examples/widget_barchart/README.md +0 -58
  139. data/examples/widget_barchart/app.rb +0 -240
  140. data/examples/widget_block/README.md +0 -44
  141. data/examples/widget_block/app.rb +0 -258
  142. data/examples/widget_box/README.md +0 -54
  143. data/examples/widget_box/app.rb +0 -255
  144. data/examples/widget_calendar/README.md +0 -48
  145. data/examples/widget_calendar/app.rb +0 -115
  146. data/examples/widget_canvas/README.md +0 -31
  147. data/examples/widget_canvas/app.rb +0 -130
  148. data/examples/widget_cell/README.md +0 -45
  149. data/examples/widget_cell/app.rb +0 -112
  150. data/examples/widget_center/README.md +0 -33
  151. data/examples/widget_center/app.rb +0 -118
  152. data/examples/widget_chart/README.md +0 -50
  153. data/examples/widget_chart/app.rb +0 -220
  154. data/examples/widget_gauge/README.md +0 -50
  155. data/examples/widget_gauge/app.rb +0 -229
  156. data/examples/widget_layout_split/README.md +0 -53
  157. data/examples/widget_layout_split/app.rb +0 -260
  158. data/examples/widget_line_gauge/README.md +0 -50
  159. data/examples/widget_line_gauge/app.rb +0 -219
  160. data/examples/widget_list/README.md +0 -58
  161. data/examples/widget_list/app.rb +0 -382
  162. data/examples/widget_map/README.md +0 -48
  163. data/examples/widget_map/app.rb +0 -95
  164. data/examples/widget_overlay/README.md +0 -45
  165. data/examples/widget_overlay/app.rb +0 -250
  166. data/examples/widget_popup/README.md +0 -45
  167. data/examples/widget_popup/app.rb +0 -106
  168. data/examples/widget_ratatui_logo/README.md +0 -43
  169. data/examples/widget_ratatui_logo/app.rb +0 -104
  170. data/examples/widget_ratatui_mascot/README.md +0 -43
  171. data/examples/widget_ratatui_mascot/app.rb +0 -95
  172. data/examples/widget_rect/README.md +0 -53
  173. data/examples/widget_rect/app.rb +0 -222
  174. data/examples/widget_render/README.md +0 -46
  175. data/examples/widget_render/app.rb +0 -186
  176. data/examples/widget_render/app.rbs +0 -41
  177. data/examples/widget_rich_text/README.md +0 -44
  178. data/examples/widget_rich_text/app.rb +0 -193
  179. data/examples/widget_scroll_text/README.md +0 -46
  180. data/examples/widget_scroll_text/app.rb +0 -109
  181. data/examples/widget_scrollbar/README.md +0 -46
  182. data/examples/widget_scrollbar/app.rb +0 -155
  183. data/examples/widget_sparkline/README.md +0 -51
  184. data/examples/widget_sparkline/app.rb +0 -277
  185. data/examples/widget_style_colors/README.md +0 -43
  186. data/examples/widget_style_colors/app.rb +0 -83
  187. data/examples/widget_table/README.md +0 -57
  188. data/examples/widget_table/app.rb +0 -285
  189. data/examples/widget_tabs/README.md +0 -50
  190. data/examples/widget_tabs/app.rb +0 -183
  191. data/examples/widget_text_width/README.md +0 -44
  192. data/examples/widget_text_width/app.rb +0 -117
  193. data/migrate_to_buffer.rb +0 -145
  194. data/mise.toml +0 -8
  195. data/tasks/autodoc/examples.rb +0 -87
  196. data/tasks/autodoc/member.rb +0 -58
  197. data/tasks/autodoc/name.rb +0 -21
  198. data/tasks/autodoc.rake +0 -21
  199. data/tasks/bump/bump_workflow.rb +0 -49
  200. data/tasks/bump/cargo_lockfile.rb +0 -21
  201. data/tasks/bump/changelog.rb +0 -104
  202. data/tasks/bump/header.rb +0 -32
  203. data/tasks/bump/history.rb +0 -32
  204. data/tasks/bump/links.rb +0 -69
  205. data/tasks/bump/manifest.rb +0 -33
  206. data/tasks/bump/patch_release.rb +0 -19
  207. data/tasks/bump/release_branch.rb +0 -17
  208. data/tasks/bump/release_from_trunk.rb +0 -49
  209. data/tasks/bump/repository.rb +0 -54
  210. data/tasks/bump/ruby_gem.rb +0 -29
  211. data/tasks/bump/sem_ver.rb +0 -44
  212. data/tasks/bump/unreleased_section.rb +0 -73
  213. data/tasks/bump.rake +0 -61
  214. data/tasks/doc/documentation.rb +0 -59
  215. data/tasks/doc/link/file_url.rb +0 -30
  216. data/tasks/doc/link/relative_path.rb +0 -61
  217. data/tasks/doc/link/web_url.rb +0 -55
  218. data/tasks/doc/link.rb +0 -52
  219. data/tasks/doc/link_audit.rb +0 -116
  220. data/tasks/doc/problem.rb +0 -40
  221. data/tasks/doc/source_file.rb +0 -93
  222. data/tasks/doc.rake +0 -905
  223. data/tasks/example_viewer.html.erb +0 -172
  224. data/tasks/extension.rake +0 -14
  225. data/tasks/license/headers_md.rb +0 -223
  226. data/tasks/license/headers_rb.rb +0 -210
  227. data/tasks/license/license_utils.rb +0 -130
  228. data/tasks/license/snippets_md.rb +0 -315
  229. data/tasks/license/snippets_rdoc.rb +0 -150
  230. data/tasks/license.rake +0 -91
  231. data/tasks/lint.rake +0 -170
  232. data/tasks/rbs_predicates/predicate_catalog.rb +0 -52
  233. data/tasks/rbs_predicates/predicate_tests.rb +0 -124
  234. data/tasks/rbs_predicates/rbs_signature.rb +0 -63
  235. data/tasks/rbs_predicates.rake +0 -31
  236. data/tasks/rdoc_config.rb +0 -29
  237. data/tasks/resources/build.yml.erb +0 -60
  238. data/tasks/resources/index.html.erb +0 -141
  239. data/tasks/resources/rubies.yml +0 -7
  240. data/tasks/sourcehut.rake +0 -122
  241. data/tasks/steep.rake +0 -11
  242. data/tasks/terminal_preview/app_screenshot.rb +0 -45
  243. data/tasks/terminal_preview/crash_report.rb +0 -54
  244. data/tasks/terminal_preview/example_app.rb +0 -27
  245. data/tasks/terminal_preview/launcher_script.rb +0 -48
  246. data/tasks/terminal_preview/preview_collection.rb +0 -60
  247. data/tasks/terminal_preview/preview_timing.rb +0 -24
  248. data/tasks/terminal_preview/safety_confirmation.rb +0 -58
  249. data/tasks/terminal_preview/saved_screenshot.rb +0 -56
  250. data/tasks/terminal_preview/system_appearance.rb +0 -13
  251. data/tasks/terminal_preview/terminal_window.rb +0 -138
  252. data/tasks/terminal_preview/window_id.rb +0 -16
  253. data/tasks/terminal_preview.rake +0 -30
  254. data/tasks/test.rake +0 -36
  255. data/tasks/website/index_page.rb +0 -30
  256. data/tasks/website/version.rb +0 -122
  257. data/tasks/website/version_menu.rb +0 -68
  258. data/tasks/website/versioned_documentation.rb +0 -83
  259. data/tasks/website/website.rb +0 -53
  260. data/tasks/website.rake +0 -28
@@ -1,155 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #--
4
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: MIT-0
6
- #++
7
-
8
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
9
- require "ratatui_ruby"
10
-
11
- # Demonstrates viewport navigation with interactive theme and orientation cycling.
12
- #
13
- # Content overflows. Users get lost in long lists without landmarks. They need to know where they are and how much is left.
14
- #
15
- # This demo showcases the <tt>Scrollbar</tt> widget. It provides an interactive playground where you can toggle orientations and cycle through different themes (Standard, Rounded, ASCII, Minimal) in real-time.
16
- #
17
- # Use it to understand how to provide spatial awareness and navigation cues for overflowing content.
18
- #
19
- # === Example
20
- #
21
- # Run the demo from the terminal:
22
- #
23
- # ruby examples/widget_scrollbar/app.rb
24
- #
25
- # rdoc-image:/doc/images/widget_scrollbar.png
26
- class WidgetScrollbar
27
- def initialize
28
- @scroll_position = 0
29
- @content_length = 50
30
- @lines = (1..@content_length).map { |i| "Line #{i}" }
31
- @orientation_index = 0
32
- @orientations = [
33
- :vertical,
34
- :vertical_right,
35
- :vertical_left,
36
- :horizontal,
37
- :horizontal_bottom,
38
- :horizontal_top,
39
- ]
40
- @theme_index = 0
41
- @themes = [
42
- {
43
- name: "Standard",
44
- track_symbol: nil,
45
- thumb_symbol: "█",
46
- track_style: nil,
47
- thumb_style: nil,
48
- begin_symbol: nil,
49
- end_symbol: nil,
50
- },
51
- {
52
- name: "Rounded",
53
- track_symbol: "│",
54
- thumb_symbol: "┃",
55
- track_style: { fg: "dark_gray" },
56
- thumb_style: { fg: "cyan" },
57
- begin_symbol: "▲",
58
- end_symbol: "▼",
59
- },
60
- {
61
- name: "ASCII",
62
- track_symbol: "|",
63
- thumb_symbol: "#",
64
- track_style: { fg: "white" },
65
- thumb_style: { fg: "red" },
66
- begin_symbol: "^",
67
- end_symbol: "v",
68
- },
69
- {
70
- name: "Minimal",
71
- track_symbol: " ",
72
- thumb_symbol: "▐",
73
- track_style: nil,
74
- thumb_style: { fg: "yellow" },
75
- begin_symbol: nil,
76
- end_symbol: nil,
77
- },
78
- ]
79
- end
80
-
81
- def run
82
- RatatuiRuby.run do |tui|
83
- @tui = tui
84
- loop do
85
- draw
86
- event = @tui.poll_event
87
- break if event == "q" || event == :ctrl_c
88
-
89
- handle_event(event)
90
- end
91
- end
92
- end
93
-
94
- private def handle_event(event)
95
- if event.mouse?
96
- case event.kind
97
- when "scroll_up"
98
- @scroll_position = [@scroll_position - 1, 0].max
99
- when "scroll_down"
100
- @scroll_position = [@scroll_position + 1, @content_length].min
101
- end
102
- end
103
-
104
- if event.key? && event.to_s == "s"
105
- @theme_index = (@theme_index + 1) % @themes.length
106
- end
107
-
108
- if event.key? && event.to_s == "o"
109
- @orientation_index = (@orientation_index + 1) % @orientations.length
110
- end
111
- end
112
-
113
- private def draw
114
- @tui.draw do |frame|
115
- # Calculate visible lines based on scroll position
116
- # In a real app, you'd want to know the height of the available area.
117
- # For this demo, we'll just show all lines but offset the text.
118
- visible_lines = @lines[@scroll_position..-1] || []
119
-
120
- # Paragraph with content
121
- theme = @themes[@theme_index]
122
- orientation = @orientations[@orientation_index]
123
-
124
- p = @tui.paragraph(
125
- text: visible_lines.join("\n"),
126
- block: @tui.block(
127
- titles: [
128
- { content: "Scroll with Mouse Wheel | Theme: #{theme[:name]} | Orientation: #{orientation}" },
129
- { content: "Press 's' to cycle theme, 'o' to cycle orientation", position: :bottom, alignment: :center },
130
- ],
131
- borders: [:all]
132
- )
133
- )
134
-
135
- # Scrollbar
136
- s = @tui.scrollbar(
137
- content_length: @content_length,
138
- position: @scroll_position,
139
- orientation:,
140
- track_symbol: theme[:track_symbol],
141
- thumb_symbol: theme[:thumb_symbol],
142
- track_style: theme[:track_style],
143
- thumb_style: theme[:thumb_style],
144
- begin_symbol: theme[:begin_symbol],
145
- end_symbol: theme[:end_symbol]
146
- )
147
-
148
- # Render paragraph first, then scrollbar on top
149
- frame.render_widget(p, frame.area)
150
- frame.render_widget(s, frame.area)
151
- end
152
- end
153
- end
154
-
155
- WidgetScrollbar.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,51 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Sparkline Widget Example
7
-
8
- [![widget_sparkline](../../doc/images/widget_sparkline.png)](app.rb)
9
-
10
- Demonstrates high-density data visualization in a condensed footprint.
11
-
12
- Users need context. A single number ("90% CPU") tells you status, but not the trend. Full charts take up too much space. Sparklines condense history into a single line, perfect for headers and dashboards.
13
-
14
- ## Features Demonstrated
15
-
16
- - **High Density**: Showing dozens of data points in a small area.
17
- - **Direction**: Rendering Left-to-Right (standard) or Right-to-Left (like a scrolling ticker).
18
- - **Gaps**: Handling `nil` values with "absent symbols" to indicate missing data.
19
- - **Styling**: Using colors and custom characters to indicate severity or type.
20
-
21
- ## Hotkeys
22
-
23
- - **Up/Down (↑/↓)**: Cycle Data Set (`data`)
24
- - **d**: Cycle Direction (`direction`)
25
- - **c**: Cycle Color (`style`)
26
- - **m**: Cycle Absent Value Marker Symbol (`absent_value_symbol`)
27
- - **s**: Cycle Absent Value Marker Style (`absent_value_style`)
28
- - **b**: Cycle Bar Character Set (`bar_set`)
29
- - **q**: Quit
30
-
31
- ## Usage
32
-
33
- <!-- SPDX-SnippetBegin -->
34
- <!--
35
- SPDX-FileCopyrightText: 2026 Kerrick Long
36
- SPDX-License-Identifier: MIT-0
37
- -->
38
- ```bash
39
- ruby examples/widget_sparkline/app.rb
40
- ```
41
- <!-- SPDX-SnippetEnd -->
42
-
43
- ## Learning Outcomes
44
-
45
- Use this example if you need to...
46
-
47
- - Add a "CPU Load" graph to your header.
48
- - Visualize stock price trends in a list row.
49
- - Monitor memory usage over the last 60 seconds.
50
-
51
- [Read the source code →](app.rb)
@@ -1,277 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #--
4
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: MIT-0
6
- #++
7
-
8
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
9
- require "ratatui_ruby"
10
-
11
- # Demonstrates high-density data visualization with interactive attribute cycling.
12
- #
13
- # Users need context. A single value ("90% CPU") tells you current status, but not the trend. Full charts take up too much room.
14
- #
15
- # This demo showcases the <tt>Sparkline</tt> widget. It provides an interactive playground where you can cycle through data sets, directions, colors, and custom bar sets.
16
- #
17
- # Use it to understand how to condense history into a single line for dashboards or headers.
18
- #
19
- # === Example
20
- #
21
- # Run the demo from the terminal:
22
- #
23
- # ruby examples/widget_sparkline/app.rb
24
- #
25
- # rdoc-image:/doc/images/widget_sparkline.png
26
- class WidgetSparkline
27
- def run
28
- RatatuiRuby.run do |tui|
29
- @tui = tui
30
- setup
31
- loop do
32
- render
33
- break if handle_input == :quit
34
- end
35
- end
36
- end
37
-
38
- private def setup
39
- # Data sets with different characteristics
40
- @data_sets = [
41
- {
42
- name: "Steady Growth",
43
- data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
44
- },
45
- {
46
- name: "With Gaps",
47
- data: [5, nil, 8, nil, 6, nil, 9, nil, 7, nil, 10, nil],
48
- },
49
- {
50
- name: "Random",
51
- data: [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8],
52
- },
53
- {
54
- name: "Sawtooth",
55
- data: [1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4],
56
- },
57
- {
58
- name: "Peaks",
59
- data: [1, 5, 1, 8, 1, 6, 1, 9, 1, 7, 1, 10],
60
- },
61
- ]
62
- @data_index = 2
63
- srand(12345) # Ensure reproducible "Random" data for snapshots
64
-
65
- @directions = [
66
- { name: "Left to Right", direction: :left_to_right },
67
- { name: "Right to Left", direction: :right_to_left },
68
- ]
69
- @direction_index = 0
70
-
71
- @styles = [
72
- { name: "Green", style: @tui.style(fg: :green) },
73
- { name: "Yellow", style: @tui.style(fg: :yellow) },
74
- { name: "Red", style: @tui.style(fg: :red) },
75
- { name: "Cyan", style: @tui.style(fg: :cyan) },
76
- { name: "Magenta", style: @tui.style(fg: :magenta) },
77
- ]
78
- @style_index = 3
79
-
80
- @absent_symbols = [
81
- { name: "None", symbol: nil },
82
- { name: "Dot (·)", symbol: "·" },
83
- { name: "Square (▫)", symbol: "▫" },
84
- { name: "Dash (-)", symbol: "-" },
85
- { name: "Underscore (_)", symbol: "_" },
86
- ]
87
- @absent_symbol_index = 1
88
-
89
- @absent_styles = [
90
- { name: "Default", style: nil },
91
- { name: "Dark Gray", style: @tui.style(fg: :dark_gray) },
92
- { name: "Dim Red", style: @tui.style(fg: :red, modifiers: [:dim]) },
93
- { name: "Dim Yellow", style: @tui.style(fg: :yellow, modifiers: [:dim]) },
94
- ]
95
- @absent_style_index = 2
96
-
97
- @bar_sets = [
98
- { name: "Default (Block)", set: nil },
99
- {
100
- name: "Numbers (0-8)",
101
- set: {
102
- 0 => "0", 1 => "1", 2 => "2", 3 => "3", 4 => "4", 5 => "5", 6 => "6", 7 => "7", 8 => "8"
103
- },
104
- },
105
- { name: "ASCII (Heights)", set: [" ", "_", ".", "-", "=", "+", "*", "#", "@"] },
106
- ]
107
- @bar_set_index = 0
108
-
109
- @hotkey_style = @tui.style(modifiers: [:bold, :underlined])
110
- end
111
-
112
- private def render
113
- @tui.draw do |frame|
114
- data_set = @data_sets[@data_index]
115
- direction = @directions[@direction_index][:direction]
116
- style = @styles[@style_index][:style]
117
- absent_symbol = @absent_symbols[@absent_symbol_index][:symbol]
118
- absent_value_style = @absent_styles[@absent_style_index][:style]
119
- bar_set = @bar_sets[@bar_set_index][:set]
120
-
121
- # Use static data for clarity when cycling options
122
- current_data = data_set[:data]
123
-
124
- layout = @tui.layout_split(
125
- frame.area,
126
- direction: :vertical,
127
- constraints: [
128
- @tui.constraint_fill(1),
129
- @tui.constraint_length(6),
130
- ]
131
- )
132
-
133
- # Main content area with multiple sparkline examples
134
- main_content_area = layout[0]
135
- main_layout = @tui.layout_split(
136
- main_content_area,
137
- direction: :vertical,
138
- constraints: [
139
- @tui.constraint_length(1),
140
- @tui.constraint_length(3),
141
- @tui.constraint_length(3),
142
- @tui.constraint_length(3),
143
- @tui.constraint_length(3),
144
- @tui.constraint_fill(1),
145
- ]
146
- )
147
-
148
- frame.render_widget(
149
- @tui.paragraph(text: "Sparkline Widget - Cycle attributes with hotkeys"),
150
- main_layout[0]
151
- )
152
-
153
- # Sparkline 1: Main interactive sparkline
154
- frame.render_widget(
155
- @tui.sparkline(
156
- data: current_data,
157
- direction:,
158
- style:,
159
- absent_value_symbol: absent_symbol,
160
- absent_value_style:,
161
- bar_set:,
162
- block: @tui.block(title: "Interactive Sparkline")
163
- ),
164
- main_layout[1]
165
- )
166
-
167
- # Sparkline 2: Same data, opposite direction
168
- frame.render_widget(
169
- @tui.sparkline(
170
- data: current_data.reverse,
171
- direction:,
172
- style:,
173
- absent_value_symbol: absent_symbol,
174
- absent_value_style:,
175
- bar_set:,
176
- block: @tui.block(title: "Reversed Data")
177
- ),
178
- main_layout[2]
179
- )
180
-
181
- # Sparkline 3: Without absent value symbol (for comparison)
182
- frame.render_widget(
183
- @tui.sparkline(
184
- data: current_data,
185
- direction:,
186
- style:,
187
- bar_set:,
188
- block: @tui.block(title: "Without Absent Marker")
189
- ),
190
- main_layout[3]
191
- )
192
-
193
- # Sparkline 4: Gap pattern responsive to absent marker controls
194
- frame.render_widget(
195
- @tui.sparkline(
196
- data: [5, nil, 8, nil, 6, nil, 9, nil, 7, nil, 10, nil],
197
- direction:,
198
- style: @tui.style(fg: :blue),
199
- absent_value_symbol: absent_symbol,
200
- absent_value_style:,
201
- bar_set:,
202
- block: @tui.block(title: "Gap Pattern (Responsive)")
203
- ),
204
- main_layout[4]
205
- )
206
-
207
- # Bottom control panel
208
- control_area = layout[1]
209
- frame.render_widget(
210
- @tui.block(
211
- title: "Controls",
212
- borders: [:all],
213
- children: [
214
- @tui.paragraph(
215
- text: [
216
- # Line 1: Data
217
- @tui.text_line(spans: [
218
- @tui.text_span(content: "↑/↓", style: @hotkey_style),
219
- @tui.text_span(content: ": Data (#{@data_sets[@data_index][:name]})"),
220
- ]),
221
- # Line 2: View
222
- @tui.text_line(spans: [
223
- @tui.text_span(content: "d", style: @hotkey_style),
224
- @tui.text_span(content: ": Direction (#{@directions[@direction_index][:name]}) "),
225
- @tui.text_span(content: "c", style: @hotkey_style),
226
- @tui.text_span(content: ": Color (#{@styles[@style_index][:name]})"),
227
- ]),
228
- # Line 3: Markers
229
- @tui.text_line(spans: [
230
- @tui.text_span(content: "m", style: @hotkey_style),
231
- @tui.text_span(content: ": Absent Value Symbol (#{@absent_symbols[@absent_symbol_index][:name]}) "),
232
- @tui.text_span(content: "s", style: @hotkey_style),
233
- @tui.text_span(content: ": Absent Value Style (#{@absent_styles[@absent_style_index][:name]})"),
234
- ]),
235
- # Line 4: General
236
- @tui.text_line(spans: [
237
- @tui.text_span(content: "b", style: @hotkey_style),
238
- @tui.text_span(content: ": Bar Set (#{@bar_sets[@bar_set_index][:name]}) "),
239
- @tui.text_span(content: "q", style: @hotkey_style),
240
- @tui.text_span(content: ": Quit"),
241
- ]),
242
- ]
243
- ),
244
- ]
245
- ),
246
- control_area
247
- )
248
- end
249
- end
250
-
251
- private def handle_input
252
- event = @tui.poll_event
253
-
254
- case event
255
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
256
- :quit
257
- in type: :key, code: "up"
258
- @data_index = (@data_index - 1) % @data_sets.length
259
- in type: :key, code: "down"
260
- @data_index = (@data_index + 1) % @data_sets.length
261
- in type: :key, code: "d"
262
- @direction_index = (@direction_index + 1) % @directions.length
263
- in type: :key, code: "c"
264
- @style_index = (@style_index + 1) % @styles.length
265
- in type: :key, code: "m"
266
- @absent_symbol_index = (@absent_symbol_index + 1) % @absent_symbols.length
267
- in type: :key, code: "s"
268
- @absent_style_index = (@absent_style_index + 1) % @absent_styles.length
269
- in type: :key, code: "b"
270
- @bar_set_index = (@bar_set_index + 1) % @bar_sets.length
271
- else
272
- nil
273
- end
274
- end
275
- end
276
-
277
- WidgetSparkline.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,43 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Style Colors Example
7
-
8
- [![widget_style_colors](../../doc/images/widget_style_colors.png)](app.rb)
9
-
10
- Demonstrates high-fidelity color support.
11
-
12
- Terminals support millions of colors. This example generates a mathematically precise HSL gradient to prove the rendering engine's color fidelity.
13
-
14
- ## Features Demonstrated
15
-
16
- - **HSL to RGB Conversion**: generating smooth color gradients programmatically.
17
- - **TrueColor Support**: Rendering arbitrary HEX colors.
18
-
19
- ## Hotkeys
20
-
21
- - **q** / **Ctrl+c**: Quit
22
-
23
- ## Usage
24
-
25
- <!-- SPDX-SnippetBegin -->
26
- <!--
27
- SPDX-FileCopyrightText: 2026 Kerrick Long
28
- SPDX-License-Identifier: MIT-0
29
- -->
30
- ```bash
31
- ruby examples/widget_style_colors/app.rb
32
- ```
33
- <!-- SPDX-SnippetEnd -->
34
-
35
- ## Learning Outcomes
36
-
37
- Use this example if you need to...
38
-
39
- - Create meaningful heatmaps.
40
- - Generate color palettes dynamically.
41
- - Test your terminal's color support capabilities.
42
-
43
- [Read the source code →](app.rb)
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #--
4
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: MIT-0
6
- #++
7
-
8
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
9
- require "ratatui_ruby"
10
-
11
- # Demonstrates terminal color rendering and the Color module.
12
- #
13
- # Terminal apps need vibrant colors. Specifying colors as symbols or
14
- # calculated hex strings works but limits expressiveness.
15
- #
16
- # This demo shows the Color module's constructors for creating colors
17
- # from HSL values or hex integers, producing a full-spectrum gradient.
18
- #
19
- # Use it to understand color representation and the Color.hsl/Color.hex APIs.
20
- class WidgetStyleColors
21
- def initialize
22
- @width = 80
23
- @height = 24
24
- end
25
-
26
- def run
27
- RatatuiRuby.run do |tui|
28
- loop do
29
- tui.draw do |frame|
30
- frame.render_widget(render(tui), frame.area)
31
- end
32
- event = tui.poll_event
33
- break if event.key? && (event.ctrl_c? || event == :q)
34
- end
35
- end
36
- end
37
-
38
- private def render(tui)
39
- lines = []
40
-
41
- (0...@height).each do |row|
42
- spans = []
43
- (0...@width).each do |col|
44
- hue = (col.to_f / @width) * 360.0
45
- lightness = 50.0 - ((row.to_f / @height) * 50.0)
46
-
47
- # Use Color.hsl for top half, Color.hsluv for bottom half
48
- # HSLuv provides perceptually uniform colors (same visual brightness)
49
- hex = if row < @height / 2
50
- RatatuiRuby::Style::Color.hsl(hue, 100.0, lightness)
51
- else
52
- # HSLuv: perceptually uniform - all colors appear equal brightness
53
- RatatuiRuby::Style::Color.hsluv(hue, 100.0, lightness)
54
- end
55
-
56
- # Demonstrate Style.with for concise inline styling
57
- span = tui.text_span(
58
- content: " ",
59
- style: RatatuiRuby::Style::Style.with(bg: hex)
60
- )
61
- spans << span
62
- end
63
-
64
- lines << tui.text_line(spans:)
65
- end
66
-
67
- # Also demonstrate Color.hex for the border
68
- border_color = RatatuiRuby::Style::Color.hex(0xFFD700) # Gold
69
-
70
- tui.paragraph(
71
- text: lines,
72
- block: tui.block(
73
- title: "HSL (top) vs HSLuv (bottom) - Style.with demo (Press 'q' to exit)",
74
- borders: [:all],
75
- border_type: :rounded,
76
- # Using Style.with for concise border styling
77
- border_style: RatatuiRuby::Style::Style.with(fg: border_color)
78
- )
79
- )
80
- end
81
- end
82
-
83
- WidgetStyleColors.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,57 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Table (Row, Cell) Example
7
-
8
- [![widget_table](../../doc/images/widget_table.png)](app.rb)
9
-
10
- Demonstrates advanced options for the `Table` widget, including selection, row-level highlighting, and column-level highlighting.
11
-
12
- Data grids are complex. Users expect to navigate them with keys, select rows, and clearly see which cell is active. The `Table` widget provides these features out of the box efficiently.
13
-
14
- ## Features Demonstrated
15
-
16
- - **Selection State**: Managing `selected_row` and `selected_column` to track user focus.
17
- - **Complex Highlighting**:
18
- - **Row**: Highlight the entire active row.
19
- - **Highlight Symbol:** Adding a visual indicator (like `> `) to the selected row.
20
- - **Spacing:** Adjusting `column_spacing` and `highlight_spacing` to control layout density.
21
- - **Flex Layout:** Switching between different column distribution modes (`legacy`, `start`, `space_between`, etc.).
22
- - **Offset Control:** Manually controlling the scroll position using `offset`.
23
-
24
- ## Hotkeys
25
-
26
- - **Arrows (↑/↓)**: Navigate Rows (`selected_row`)
27
- - **Arrows (←/→)**: Navigate Columns (`selected_column`)
28
- - **x**: Toggle Row Selection (`selected_row` = nil)
29
- - **s**: Cycle Table Style (`style`)
30
- - **p**: Cycle Spacing (`highlight_spacing`)
31
- - **c**: Toggle Column Highlight (`column_highlight_style`)
32
- - **z**: Toggle Cell Highlight (`cell_highlight_style`)
33
- - **o**: Cycle Offset Mode (`offset`)
34
- - **f**: Cycle Flex Mode (`flex`)
35
- - **q**: Quit
36
-
37
- ## Usage
38
-
39
- <!-- SPDX-SnippetBegin -->
40
- <!--
41
- SPDX-FileCopyrightText: 2026 Kerrick Long
42
- SPDX-License-Identifier: MIT-0
43
- -->
44
- ```bash
45
- ruby examples/widget_table/app.rb
46
- ```
47
- <!-- SPDX-SnippetEnd -->
48
-
49
- ## Learning Outcomes
50
-
51
- Use this example if you need to...
52
-
53
- - Build a file explorer or process list.
54
- - Create a data-heavy dashboard.
55
- - Handle conflicting style requirements (e.g., "Highlight this row, but make this error cell red").
56
-
57
- [Read the source code →](app.rb)