ratatui_ruby 1.0.0 → 1.0.1

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 (236) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ratatui_ruby/Cargo.lock +1 -1
  3. data/ext/ratatui_ruby/Cargo.toml +1 -1
  4. data/lib/ratatui_ruby/version.rb +1 -1
  5. metadata +1 -232
  6. data/.builds/ruby-3.2.yml +0 -54
  7. data/.builds/ruby-3.3.yml +0 -54
  8. data/.builds/ruby-3.4.yml +0 -54
  9. data/.builds/ruby-4.0.0.yml +0 -54
  10. data/.pre-commit-config.yaml +0 -16
  11. data/.rubocop.yml +0 -10
  12. data/AGENTS.md +0 -146
  13. data/CHANGELOG.md +0 -710
  14. data/README.md +0 -187
  15. data/README.rdoc +0 -302
  16. data/Rakefile +0 -11
  17. data/Steepfile +0 -49
  18. data/doc/concepts/application_architecture.md +0 -321
  19. data/doc/concepts/application_testing.md +0 -193
  20. data/doc/concepts/async.md +0 -190
  21. data/doc/concepts/custom_widgets.md +0 -247
  22. data/doc/concepts/debugging.md +0 -401
  23. data/doc/concepts/event_handling.md +0 -162
  24. data/doc/concepts/interactive_design.md +0 -146
  25. data/doc/contributors/auditing/parity.md +0 -239
  26. data/doc/contributors/design/ruby_frontend.md +0 -420
  27. data/doc/contributors/design/rust_backend.md +0 -422
  28. data/doc/contributors/design.md +0 -11
  29. data/doc/contributors/developing_examples.md +0 -400
  30. data/doc/contributors/documentation_style.md +0 -121
  31. data/doc/contributors/index.md +0 -21
  32. data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -375
  33. data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -206
  34. data/doc/contributors/todo/align/terminal.md +0 -647
  35. data/doc/contributors/todo/future_work.md +0 -169
  36. data/doc/contributors/upstream_requests/tab_rects.md +0 -173
  37. data/doc/contributors/upstream_requests/title_rects.md +0 -132
  38. data/doc/custom.css +0 -22
  39. data/doc/getting_started/quickstart.md +0 -291
  40. data/doc/getting_started/why.md +0 -93
  41. data/doc/images/app_all_events.png +0 -0
  42. data/doc/images/app_cli_rich_moments.gif +0 -0
  43. data/doc/images/app_color_picker.png +0 -0
  44. data/doc/images/app_debugging_showcase.gif +0 -0
  45. data/doc/images/app_debugging_showcase.png +0 -0
  46. data/doc/images/app_login_form.png +0 -0
  47. data/doc/images/app_stateful_interaction.png +0 -0
  48. data/doc/images/verify_quickstart_dsl.png +0 -0
  49. data/doc/images/verify_quickstart_layout.png +0 -0
  50. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  51. data/doc/images/verify_readme_usage.png +0 -0
  52. data/doc/images/widget_barchart.png +0 -0
  53. data/doc/images/widget_block.png +0 -0
  54. data/doc/images/widget_box.png +0 -0
  55. data/doc/images/widget_calendar.png +0 -0
  56. data/doc/images/widget_canvas.png +0 -0
  57. data/doc/images/widget_cell.png +0 -0
  58. data/doc/images/widget_center.png +0 -0
  59. data/doc/images/widget_chart.png +0 -0
  60. data/doc/images/widget_gauge.png +0 -0
  61. data/doc/images/widget_layout_split.png +0 -0
  62. data/doc/images/widget_line_gauge.png +0 -0
  63. data/doc/images/widget_list.png +0 -0
  64. data/doc/images/widget_map.png +0 -0
  65. data/doc/images/widget_overlay.png +0 -0
  66. data/doc/images/widget_popup.png +0 -0
  67. data/doc/images/widget_ratatui_logo.png +0 -0
  68. data/doc/images/widget_ratatui_mascot.png +0 -0
  69. data/doc/images/widget_rect.png +0 -0
  70. data/doc/images/widget_render.png +0 -0
  71. data/doc/images/widget_rich_text.png +0 -0
  72. data/doc/images/widget_scroll_text.png +0 -0
  73. data/doc/images/widget_scrollbar.png +0 -0
  74. data/doc/images/widget_sparkline.png +0 -0
  75. data/doc/images/widget_style_colors.png +0 -0
  76. data/doc/images/widget_table.png +0 -0
  77. data/doc/images/widget_tabs.png +0 -0
  78. data/doc/images/widget_text_width.png +0 -0
  79. data/doc/index.md +0 -39
  80. data/doc/troubleshooting/async.md +0 -4
  81. data/doc/troubleshooting/terminal_limitations.md +0 -131
  82. data/doc/troubleshooting/tui_output.md +0 -197
  83. data/examples/app_all_events/README.md +0 -114
  84. data/examples/app_all_events/app.rb +0 -98
  85. data/examples/app_all_events/model/app_model.rb +0 -159
  86. data/examples/app_all_events/model/event_color_cycle.rb +0 -43
  87. data/examples/app_all_events/model/event_entry.rb +0 -94
  88. data/examples/app_all_events/model/msg.rb +0 -39
  89. data/examples/app_all_events/model/timestamp.rb +0 -56
  90. data/examples/app_all_events/update.rb +0 -75
  91. data/examples/app_all_events/view/app_view.rb +0 -80
  92. data/examples/app_all_events/view/controls_view.rb +0 -54
  93. data/examples/app_all_events/view/counts_view.rb +0 -61
  94. data/examples/app_all_events/view/live_view.rb +0 -72
  95. data/examples/app_all_events/view/log_view.rb +0 -57
  96. data/examples/app_all_events/view.rb +0 -9
  97. data/examples/app_cli_rich_moments/README.md +0 -81
  98. data/examples/app_cli_rich_moments/app.rb +0 -189
  99. data/examples/app_color_picker/README.md +0 -156
  100. data/examples/app_color_picker/app.rb +0 -76
  101. data/examples/app_color_picker/clipboard.rb +0 -86
  102. data/examples/app_color_picker/color.rb +0 -193
  103. data/examples/app_color_picker/controls.rb +0 -92
  104. data/examples/app_color_picker/copy_dialog.rb +0 -168
  105. data/examples/app_color_picker/export_pane.rb +0 -128
  106. data/examples/app_color_picker/harmony.rb +0 -58
  107. data/examples/app_color_picker/input.rb +0 -176
  108. data/examples/app_color_picker/main_container.rb +0 -180
  109. data/examples/app_color_picker/palette.rb +0 -111
  110. data/examples/app_debugging_showcase/README.md +0 -119
  111. data/examples/app_debugging_showcase/app.rb +0 -318
  112. data/examples/app_login_form/README.md +0 -58
  113. data/examples/app_login_form/app.rb +0 -109
  114. data/examples/app_stateful_interaction/README.md +0 -35
  115. data/examples/app_stateful_interaction/app.rb +0 -328
  116. data/examples/timeout_demo.rb +0 -45
  117. data/examples/verify_quickstart_dsl/README.md +0 -55
  118. data/examples/verify_quickstart_dsl/app.rb +0 -49
  119. data/examples/verify_quickstart_layout/README.md +0 -77
  120. data/examples/verify_quickstart_layout/app.rb +0 -73
  121. data/examples/verify_quickstart_lifecycle/README.md +0 -68
  122. data/examples/verify_quickstart_lifecycle/app.rb +0 -62
  123. data/examples/verify_readme_usage/README.md +0 -49
  124. data/examples/verify_readme_usage/app.rb +0 -42
  125. data/examples/verify_website_managed/README.md +0 -48
  126. data/examples/verify_website_managed/app.rb +0 -36
  127. data/examples/verify_website_menu/README.md +0 -60
  128. data/examples/verify_website_menu/app.rb +0 -84
  129. data/examples/verify_website_spinner/README.md +0 -44
  130. data/examples/verify_website_spinner/app.rb +0 -34
  131. data/examples/widget_barchart/README.md +0 -58
  132. data/examples/widget_barchart/app.rb +0 -240
  133. data/examples/widget_block/README.md +0 -44
  134. data/examples/widget_block/app.rb +0 -258
  135. data/examples/widget_box/README.md +0 -54
  136. data/examples/widget_box/app.rb +0 -255
  137. data/examples/widget_calendar/README.md +0 -48
  138. data/examples/widget_calendar/app.rb +0 -115
  139. data/examples/widget_canvas/README.md +0 -31
  140. data/examples/widget_canvas/app.rb +0 -130
  141. data/examples/widget_cell/README.md +0 -45
  142. data/examples/widget_cell/app.rb +0 -112
  143. data/examples/widget_center/README.md +0 -33
  144. data/examples/widget_center/app.rb +0 -118
  145. data/examples/widget_chart/README.md +0 -50
  146. data/examples/widget_chart/app.rb +0 -220
  147. data/examples/widget_gauge/README.md +0 -50
  148. data/examples/widget_gauge/app.rb +0 -229
  149. data/examples/widget_layout_split/README.md +0 -53
  150. data/examples/widget_layout_split/app.rb +0 -260
  151. data/examples/widget_line_gauge/README.md +0 -50
  152. data/examples/widget_line_gauge/app.rb +0 -219
  153. data/examples/widget_list/README.md +0 -58
  154. data/examples/widget_list/app.rb +0 -384
  155. data/examples/widget_map/README.md +0 -48
  156. data/examples/widget_map/app.rb +0 -95
  157. data/examples/widget_overlay/README.md +0 -45
  158. data/examples/widget_overlay/app.rb +0 -250
  159. data/examples/widget_popup/README.md +0 -45
  160. data/examples/widget_popup/app.rb +0 -106
  161. data/examples/widget_ratatui_logo/README.md +0 -43
  162. data/examples/widget_ratatui_logo/app.rb +0 -104
  163. data/examples/widget_ratatui_mascot/README.md +0 -43
  164. data/examples/widget_ratatui_mascot/app.rb +0 -95
  165. data/examples/widget_rect/README.md +0 -53
  166. data/examples/widget_rect/app.rb +0 -222
  167. data/examples/widget_render/README.md +0 -46
  168. data/examples/widget_render/app.rb +0 -186
  169. data/examples/widget_render/app.rbs +0 -41
  170. data/examples/widget_rich_text/README.md +0 -44
  171. data/examples/widget_rich_text/app.rb +0 -193
  172. data/examples/widget_scroll_text/README.md +0 -46
  173. data/examples/widget_scroll_text/app.rb +0 -109
  174. data/examples/widget_scrollbar/README.md +0 -46
  175. data/examples/widget_scrollbar/app.rb +0 -155
  176. data/examples/widget_sparkline/README.md +0 -51
  177. data/examples/widget_sparkline/app.rb +0 -277
  178. data/examples/widget_style_colors/README.md +0 -43
  179. data/examples/widget_style_colors/app.rb +0 -83
  180. data/examples/widget_table/README.md +0 -57
  181. data/examples/widget_table/app.rb +0 -279
  182. data/examples/widget_tabs/README.md +0 -50
  183. data/examples/widget_tabs/app.rb +0 -183
  184. data/examples/widget_text_width/README.md +0 -44
  185. data/examples/widget_text_width/app.rb +0 -117
  186. data/migrate_to_buffer.rb +0 -145
  187. data/mise.toml +0 -8
  188. data/tasks/autodoc/examples.rb +0 -87
  189. data/tasks/autodoc/member.rb +0 -58
  190. data/tasks/autodoc/name.rb +0 -21
  191. data/tasks/autodoc.rake +0 -21
  192. data/tasks/bump/cargo_lockfile.rb +0 -21
  193. data/tasks/bump/changelog.rb +0 -47
  194. data/tasks/bump/header.rb +0 -32
  195. data/tasks/bump/history.rb +0 -32
  196. data/tasks/bump/links.rb +0 -69
  197. data/tasks/bump/manifest.rb +0 -33
  198. data/tasks/bump/ruby_gem.rb +0 -49
  199. data/tasks/bump/sem_ver.rb +0 -40
  200. data/tasks/bump/unreleased_section.rb +0 -56
  201. data/tasks/bump.rake +0 -51
  202. data/tasks/doc.rake +0 -887
  203. data/tasks/example_viewer.html.erb +0 -172
  204. data/tasks/extension.rake +0 -14
  205. data/tasks/license/headers_md.rb +0 -223
  206. data/tasks/license/headers_rb.rb +0 -210
  207. data/tasks/license/license_utils.rb +0 -130
  208. data/tasks/license/snippets_md.rb +0 -315
  209. data/tasks/license/snippets_rdoc.rb +0 -150
  210. data/tasks/license.rake +0 -91
  211. data/tasks/lint.rake +0 -170
  212. data/tasks/rdoc_config.rb +0 -29
  213. data/tasks/resources/build.yml.erb +0 -60
  214. data/tasks/resources/index.html.erb +0 -141
  215. data/tasks/resources/rubies.yml +0 -7
  216. data/tasks/sourcehut.rake +0 -110
  217. data/tasks/steep.rake +0 -11
  218. data/tasks/terminal_preview/app_screenshot.rb +0 -45
  219. data/tasks/terminal_preview/crash_report.rb +0 -54
  220. data/tasks/terminal_preview/example_app.rb +0 -27
  221. data/tasks/terminal_preview/launcher_script.rb +0 -48
  222. data/tasks/terminal_preview/preview_collection.rb +0 -60
  223. data/tasks/terminal_preview/preview_timing.rb +0 -24
  224. data/tasks/terminal_preview/safety_confirmation.rb +0 -58
  225. data/tasks/terminal_preview/saved_screenshot.rb +0 -56
  226. data/tasks/terminal_preview/system_appearance.rb +0 -13
  227. data/tasks/terminal_preview/terminal_window.rb +0 -138
  228. data/tasks/terminal_preview/window_id.rb +0 -16
  229. data/tasks/terminal_preview.rake +0 -30
  230. data/tasks/test.rake +0 -33
  231. data/tasks/website/index_page.rb +0 -30
  232. data/tasks/website/version.rb +0 -127
  233. data/tasks/website/version_menu.rb +0 -68
  234. data/tasks/website/versioned_documentation.rb +0 -83
  235. data/tasks/website/website.rb +0 -53
  236. 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)