ratatui_ruby 1.3.0 → 1.4.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 (263) 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/test_helper/snapshot.rb +58 -10
  6. data/lib/ratatui_ruby/test_helper/subprocess_timeout.rb +35 -0
  7. data/lib/ratatui_ruby/test_helper.rb +2 -0
  8. data/lib/ratatui_ruby/version.rb +1 -1
  9. metadata +17 -270
  10. data/.builds/ruby-3.2.yml +0 -54
  11. data/.builds/ruby-3.3.yml +0 -54
  12. data/.builds/ruby-3.4.yml +0 -54
  13. data/.builds/ruby-4.0.0.yml +0 -54
  14. data/.pre-commit-config.yaml +0 -16
  15. data/.rubocop.yml +0 -10
  16. data/AGENTS.md +0 -147
  17. data/CHANGELOG.md +0 -771
  18. data/README.md +0 -187
  19. data/README.rdoc +0 -302
  20. data/Rakefile +0 -11
  21. data/Steepfile +0 -50
  22. data/doc/concepts/application_architecture.md +0 -321
  23. data/doc/concepts/application_testing.md +0 -193
  24. data/doc/concepts/async.md +0 -190
  25. data/doc/concepts/custom_widgets.md +0 -247
  26. data/doc/concepts/debugging.md +0 -401
  27. data/doc/concepts/event_handling.md +0 -162
  28. data/doc/concepts/interactive_design.md +0 -146
  29. data/doc/contributors/auditing/parity.md +0 -239
  30. data/doc/contributors/design/ruby_frontend.md +0 -448
  31. data/doc/contributors/design/rust_backend.md +0 -434
  32. data/doc/contributors/design.md +0 -11
  33. data/doc/contributors/developing_examples.md +0 -400
  34. data/doc/contributors/documentation_style.md +0 -121
  35. data/doc/contributors/index.md +0 -21
  36. data/doc/contributors/releasing.md +0 -215
  37. data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -381
  38. data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -200
  39. data/doc/contributors/todo/align/term.md +0 -351
  40. data/doc/contributors/todo/align/terminal.md +0 -647
  41. data/doc/contributors/todo/future_work.md +0 -169
  42. data/doc/contributors/upstream_requests/paragraph_span_rects.md +0 -259
  43. data/doc/contributors/upstream_requests/tab_rects.md +0 -173
  44. data/doc/contributors/upstream_requests/title_rects.md +0 -132
  45. data/doc/custom.css +0 -22
  46. data/doc/getting_started/quickstart.md +0 -291
  47. data/doc/getting_started/why.md +0 -93
  48. data/doc/images/app_all_events.png +0 -0
  49. data/doc/images/app_cli_rich_moments.gif +0 -0
  50. data/doc/images/app_color_picker.png +0 -0
  51. data/doc/images/app_debugging_showcase.gif +0 -0
  52. data/doc/images/app_debugging_showcase.png +0 -0
  53. data/doc/images/app_external_editor.gif +0 -0
  54. data/doc/images/app_login_form.png +0 -0
  55. data/doc/images/app_stateful_interaction.png +0 -0
  56. data/doc/images/verify_quickstart_dsl.png +0 -0
  57. data/doc/images/verify_quickstart_layout.png +0 -0
  58. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  59. data/doc/images/verify_readme_usage.png +0 -0
  60. data/doc/images/widget_barchart.png +0 -0
  61. data/doc/images/widget_block.png +0 -0
  62. data/doc/images/widget_box.png +0 -0
  63. data/doc/images/widget_calendar.png +0 -0
  64. data/doc/images/widget_canvas.png +0 -0
  65. data/doc/images/widget_cell.png +0 -0
  66. data/doc/images/widget_center.png +0 -0
  67. data/doc/images/widget_chart.png +0 -0
  68. data/doc/images/widget_gauge.png +0 -0
  69. data/doc/images/widget_layout_split.png +0 -0
  70. data/doc/images/widget_line_gauge.png +0 -0
  71. data/doc/images/widget_list.png +0 -0
  72. data/doc/images/widget_map.png +0 -0
  73. data/doc/images/widget_overlay.png +0 -0
  74. data/doc/images/widget_popup.png +0 -0
  75. data/doc/images/widget_ratatui_logo.png +0 -0
  76. data/doc/images/widget_ratatui_mascot.png +0 -0
  77. data/doc/images/widget_rect.png +0 -0
  78. data/doc/images/widget_render.png +0 -0
  79. data/doc/images/widget_rich_text.png +0 -0
  80. data/doc/images/widget_scroll_text.png +0 -0
  81. data/doc/images/widget_scrollbar.png +0 -0
  82. data/doc/images/widget_sparkline.png +0 -0
  83. data/doc/images/widget_style_colors.png +0 -0
  84. data/doc/images/widget_table.png +0 -0
  85. data/doc/images/widget_tabs.png +0 -0
  86. data/doc/images/widget_text_width.png +0 -0
  87. data/doc/index.md +0 -34
  88. data/doc/troubleshooting/async.md +0 -4
  89. data/doc/troubleshooting/terminal_limitations.md +0 -131
  90. data/doc/troubleshooting/tui_output.md +0 -197
  91. data/examples/app_all_events/README.md +0 -114
  92. data/examples/app_all_events/app.rb +0 -98
  93. data/examples/app_all_events/model/app_model.rb +0 -159
  94. data/examples/app_all_events/model/event_color_cycle.rb +0 -43
  95. data/examples/app_all_events/model/event_entry.rb +0 -94
  96. data/examples/app_all_events/model/msg.rb +0 -39
  97. data/examples/app_all_events/model/timestamp.rb +0 -56
  98. data/examples/app_all_events/update.rb +0 -75
  99. data/examples/app_all_events/view/app_view.rb +0 -80
  100. data/examples/app_all_events/view/controls_view.rb +0 -54
  101. data/examples/app_all_events/view/counts_view.rb +0 -61
  102. data/examples/app_all_events/view/live_view.rb +0 -72
  103. data/examples/app_all_events/view/log_view.rb +0 -57
  104. data/examples/app_all_events/view.rb +0 -9
  105. data/examples/app_cli_rich_moments/README.md +0 -81
  106. data/examples/app_cli_rich_moments/app.rb +0 -189
  107. data/examples/app_color_picker/README.md +0 -156
  108. data/examples/app_color_picker/app.rb +0 -76
  109. data/examples/app_color_picker/clipboard.rb +0 -86
  110. data/examples/app_color_picker/color.rb +0 -193
  111. data/examples/app_color_picker/controls.rb +0 -92
  112. data/examples/app_color_picker/copy_dialog.rb +0 -168
  113. data/examples/app_color_picker/export_pane.rb +0 -128
  114. data/examples/app_color_picker/harmony.rb +0 -58
  115. data/examples/app_color_picker/input.rb +0 -176
  116. data/examples/app_color_picker/main_container.rb +0 -180
  117. data/examples/app_color_picker/palette.rb +0 -111
  118. data/examples/app_debugging_showcase/README.md +0 -119
  119. data/examples/app_debugging_showcase/app.rb +0 -318
  120. data/examples/app_external_editor/README.md +0 -62
  121. data/examples/app_external_editor/app.rb +0 -344
  122. data/examples/app_login_form/README.md +0 -58
  123. data/examples/app_login_form/app.rb +0 -109
  124. data/examples/app_stateful_interaction/README.md +0 -35
  125. data/examples/app_stateful_interaction/app.rb +0 -328
  126. data/examples/timeout_demo.rb +0 -45
  127. data/examples/verify_quickstart_dsl/README.md +0 -55
  128. data/examples/verify_quickstart_dsl/app.rb +0 -49
  129. data/examples/verify_quickstart_layout/README.md +0 -77
  130. data/examples/verify_quickstart_layout/app.rb +0 -73
  131. data/examples/verify_quickstart_lifecycle/README.md +0 -68
  132. data/examples/verify_quickstart_lifecycle/app.rb +0 -62
  133. data/examples/verify_readme_usage/README.md +0 -49
  134. data/examples/verify_readme_usage/app.rb +0 -42
  135. data/examples/verify_website_managed/README.md +0 -48
  136. data/examples/verify_website_managed/app.rb +0 -36
  137. data/examples/verify_website_menu/README.md +0 -60
  138. data/examples/verify_website_menu/app.rb +0 -84
  139. data/examples/verify_website_spinner/README.md +0 -44
  140. data/examples/verify_website_spinner/app.rb +0 -34
  141. data/examples/widget_barchart/README.md +0 -58
  142. data/examples/widget_barchart/app.rb +0 -240
  143. data/examples/widget_block/README.md +0 -44
  144. data/examples/widget_block/app.rb +0 -258
  145. data/examples/widget_box/README.md +0 -54
  146. data/examples/widget_box/app.rb +0 -255
  147. data/examples/widget_calendar/README.md +0 -48
  148. data/examples/widget_calendar/app.rb +0 -115
  149. data/examples/widget_canvas/README.md +0 -31
  150. data/examples/widget_canvas/app.rb +0 -130
  151. data/examples/widget_cell/README.md +0 -45
  152. data/examples/widget_cell/app.rb +0 -112
  153. data/examples/widget_center/README.md +0 -33
  154. data/examples/widget_center/app.rb +0 -118
  155. data/examples/widget_chart/README.md +0 -50
  156. data/examples/widget_chart/app.rb +0 -220
  157. data/examples/widget_gauge/README.md +0 -50
  158. data/examples/widget_gauge/app.rb +0 -229
  159. data/examples/widget_layout_split/README.md +0 -53
  160. data/examples/widget_layout_split/app.rb +0 -260
  161. data/examples/widget_line_gauge/README.md +0 -50
  162. data/examples/widget_line_gauge/app.rb +0 -219
  163. data/examples/widget_list/README.md +0 -58
  164. data/examples/widget_list/app.rb +0 -382
  165. data/examples/widget_map/README.md +0 -48
  166. data/examples/widget_map/app.rb +0 -95
  167. data/examples/widget_overlay/README.md +0 -45
  168. data/examples/widget_overlay/app.rb +0 -250
  169. data/examples/widget_popup/README.md +0 -45
  170. data/examples/widget_popup/app.rb +0 -106
  171. data/examples/widget_ratatui_logo/README.md +0 -43
  172. data/examples/widget_ratatui_logo/app.rb +0 -104
  173. data/examples/widget_ratatui_mascot/README.md +0 -43
  174. data/examples/widget_ratatui_mascot/app.rb +0 -95
  175. data/examples/widget_rect/README.md +0 -53
  176. data/examples/widget_rect/app.rb +0 -222
  177. data/examples/widget_render/README.md +0 -46
  178. data/examples/widget_render/app.rb +0 -186
  179. data/examples/widget_render/app.rbs +0 -41
  180. data/examples/widget_rich_text/README.md +0 -44
  181. data/examples/widget_rich_text/app.rb +0 -193
  182. data/examples/widget_scroll_text/README.md +0 -46
  183. data/examples/widget_scroll_text/app.rb +0 -109
  184. data/examples/widget_scrollbar/README.md +0 -46
  185. data/examples/widget_scrollbar/app.rb +0 -155
  186. data/examples/widget_sparkline/README.md +0 -51
  187. data/examples/widget_sparkline/app.rb +0 -277
  188. data/examples/widget_style_colors/README.md +0 -43
  189. data/examples/widget_style_colors/app.rb +0 -83
  190. data/examples/widget_table/README.md +0 -57
  191. data/examples/widget_table/app.rb +0 -285
  192. data/examples/widget_tabs/README.md +0 -50
  193. data/examples/widget_tabs/app.rb +0 -183
  194. data/examples/widget_text_width/README.md +0 -44
  195. data/examples/widget_text_width/app.rb +0 -117
  196. data/migrate_to_buffer.rb +0 -145
  197. data/mise.toml +0 -8
  198. data/tasks/autodoc/examples.rb +0 -87
  199. data/tasks/autodoc/member.rb +0 -58
  200. data/tasks/autodoc/name.rb +0 -21
  201. data/tasks/autodoc.rake +0 -21
  202. data/tasks/bump/bump_workflow.rb +0 -49
  203. data/tasks/bump/cargo_lockfile.rb +0 -21
  204. data/tasks/bump/changelog.rb +0 -104
  205. data/tasks/bump/header.rb +0 -32
  206. data/tasks/bump/history.rb +0 -32
  207. data/tasks/bump/links.rb +0 -69
  208. data/tasks/bump/manifest.rb +0 -33
  209. data/tasks/bump/patch_release.rb +0 -19
  210. data/tasks/bump/release_branch.rb +0 -17
  211. data/tasks/bump/release_from_trunk.rb +0 -49
  212. data/tasks/bump/repository.rb +0 -54
  213. data/tasks/bump/ruby_gem.rb +0 -29
  214. data/tasks/bump/sem_ver.rb +0 -44
  215. data/tasks/bump/unreleased_section.rb +0 -73
  216. data/tasks/bump.rake +0 -61
  217. data/tasks/doc/documentation.rb +0 -59
  218. data/tasks/doc/link/file_url.rb +0 -30
  219. data/tasks/doc/link/relative_path.rb +0 -61
  220. data/tasks/doc/link/web_url.rb +0 -55
  221. data/tasks/doc/link.rb +0 -52
  222. data/tasks/doc/link_audit.rb +0 -116
  223. data/tasks/doc/problem.rb +0 -40
  224. data/tasks/doc/source_file.rb +0 -93
  225. data/tasks/doc.rake +0 -905
  226. data/tasks/example_viewer.html.erb +0 -172
  227. data/tasks/extension.rake +0 -14
  228. data/tasks/license/headers_md.rb +0 -223
  229. data/tasks/license/headers_rb.rb +0 -210
  230. data/tasks/license/license_utils.rb +0 -130
  231. data/tasks/license/snippets_md.rb +0 -315
  232. data/tasks/license/snippets_rdoc.rb +0 -150
  233. data/tasks/license.rake +0 -91
  234. data/tasks/lint.rake +0 -170
  235. data/tasks/rbs_predicates/predicate_catalog.rb +0 -52
  236. data/tasks/rbs_predicates/predicate_tests.rb +0 -124
  237. data/tasks/rbs_predicates/rbs_signature.rb +0 -63
  238. data/tasks/rbs_predicates.rake +0 -31
  239. data/tasks/rdoc_config.rb +0 -29
  240. data/tasks/resources/build.yml.erb +0 -60
  241. data/tasks/resources/index.html.erb +0 -141
  242. data/tasks/resources/rubies.yml +0 -7
  243. data/tasks/sourcehut.rake +0 -122
  244. data/tasks/steep.rake +0 -11
  245. data/tasks/terminal_preview/app_screenshot.rb +0 -45
  246. data/tasks/terminal_preview/crash_report.rb +0 -54
  247. data/tasks/terminal_preview/example_app.rb +0 -27
  248. data/tasks/terminal_preview/launcher_script.rb +0 -48
  249. data/tasks/terminal_preview/preview_collection.rb +0 -60
  250. data/tasks/terminal_preview/preview_timing.rb +0 -24
  251. data/tasks/terminal_preview/safety_confirmation.rb +0 -58
  252. data/tasks/terminal_preview/saved_screenshot.rb +0 -56
  253. data/tasks/terminal_preview/system_appearance.rb +0 -13
  254. data/tasks/terminal_preview/terminal_window.rb +0 -138
  255. data/tasks/terminal_preview/window_id.rb +0 -16
  256. data/tasks/terminal_preview.rake +0 -30
  257. data/tasks/test.rake +0 -36
  258. data/tasks/website/index_page.rb +0 -30
  259. data/tasks/website/version.rb +0 -122
  260. data/tasks/website/version_menu.rb +0 -68
  261. data/tasks/website/versioned_documentation.rb +0 -83
  262. data/tasks/website/website.rb +0 -53
  263. data/tasks/website.rake +0 -28
@@ -1,255 +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 visual container attributes with interactive cycling.
12
- #
13
- # Widgets often float in void. Without boundaries, interfaces become a chaotic mess of text. Users need structure to parse information.
14
- #
15
- # This demo showcases the <tt>Block</tt> widget. It provides an interactive playground where you can cycle through different border types, colors, and title alignments in real-time.
16
- #
17
- # Use it to understand how to define distinct areas and create visual hierarchy in your terminal interface.
18
- #
19
- # === Example
20
- #
21
- # Run the demo from the terminal:
22
- #
23
- # ruby examples/widget_box/app.rb
24
- #
25
- # rdoc-image:/doc/images/widget_box.png
26
- class WidgetBox
27
- def initialize
28
- # Border Types (ratatui native styles)
29
- @border_types = [
30
- { name: "Plain", type: :plain },
31
- { name: "Rounded", type: :rounded },
32
- { name: "Double", type: :double },
33
- { name: "Thick", type: :thick },
34
- { name: "Quadrant Inside", type: :quadrant_inside },
35
- { name: "Quadrant Outside", type: :quadrant_outside },
36
- ]
37
- @border_type_index = 0
38
-
39
- # Custom Border Sets
40
- # NOTE: We define these ONCE in initialize for efficiency.
41
- @border_sets = [
42
- { name: "None", set: nil },
43
- {
44
- name: "Digits (Short)",
45
- set: {
46
- tl: "1",
47
- tr: "2",
48
- bl: "3",
49
- br: "4",
50
- vl: "5",
51
- vr: "6",
52
- ht: "7",
53
- hb: "8",
54
- },
55
- },
56
- {
57
- name: "Letters (Long)",
58
- set: {
59
- top_left: "A",
60
- top_right: "B",
61
- bottom_left: "C",
62
- bottom_right: "D",
63
- vertical_left: "E",
64
- vertical_right: "F",
65
- horizontal_top: "G",
66
- horizontal_bottom: "H",
67
- },
68
- },
69
- ]
70
- @border_set_index = 0
71
-
72
- @colors = [
73
- { name: "Green", color: "green" },
74
- { name: "Red", color: "red" },
75
- { name: "Blue", color: "blue" },
76
- { name: "Yellow", color: "yellow" },
77
- { name: "Magenta", color: "magenta" },
78
- ]
79
- @color_index = 0
80
-
81
- @title_alignments = [
82
- { name: "Left", alignment: :left },
83
- { name: "Center", alignment: :center },
84
- { name: "Right", alignment: :right },
85
- ]
86
- @title_alignment_index = 0
87
-
88
- @styles = [
89
- { name: "Default", style: nil },
90
- { name: "Blue on White", style: { fg: "blue", bg: "white", modifiers: [:bold] } },
91
- ]
92
- @style_index = 0
93
-
94
- @title_styles = [
95
- { name: "Default", style: nil },
96
- { name: "Yellow Bold Underlined", style: { fg: "yellow", modifiers: [:bold, :underlined] } },
97
- ]
98
- @title_style_index = 0
99
-
100
- @border_styles = [
101
- { name: "Default (no border style)", style: nil },
102
- { name: "Bold Red", style: { fg: "red", modifiers: [:bold] } },
103
- { name: "Cyan Italic", style: { fg: "cyan", modifiers: [:italic] } },
104
- { name: "Magenta Dim", style: { fg: "magenta", modifiers: [:dim] } },
105
- ]
106
- @border_style_index = 0
107
-
108
- @hotkey_style = nil # Initialized in run when tui is available
109
- end
110
-
111
- def run
112
- RatatuiRuby.run do |tui|
113
- @tui = tui
114
- @hotkey_style = tui.style(modifiers: [:bold, :underlined])
115
-
116
- loop do
117
- render
118
- break if handle_input == :quit
119
- end
120
- end
121
- end
122
-
123
- private def render
124
- # Get current values
125
- border_type_config = @border_types[@border_type_index]
126
- border_set_config = @border_sets[@border_set_index]
127
-
128
- color_config = @colors[@color_index]
129
- title_alignment_config = @title_alignments[@title_alignment_index]
130
- style_config = @styles[@style_index]
131
- title_style_config = @title_styles[@title_style_index]
132
- border_style_config = @border_styles[@border_style_index]
133
-
134
- # 1. State/View
135
- # Use border_style if explicitly set; otherwise, only apply color picker
136
- # color when no content style is set (preserves original border_color behavior)
137
- effective_border_style = if border_style_config[:style]
138
- border_style_config[:style]
139
- elsif style_config[:style].nil?
140
- @tui.style(fg: color_config[:color])
141
- end
142
-
143
- # Show overridden status if border_set is active
144
- type_display = border_type_config[:name]
145
- if border_set_config[:set]
146
- type_display += " (Overridden)"
147
- end
148
-
149
- block = @tui.block(
150
- title: "Box",
151
- title_alignment: title_alignment_config[:alignment],
152
- title_style: title_style_config[:style],
153
- borders: [:all],
154
- border_style: effective_border_style,
155
- border_type: border_type_config[:type],
156
- border_set: border_set_config[:set],
157
- style: style_config[:style]
158
- )
159
-
160
- # Main content
161
- main_panel = @tui.paragraph(
162
- text: "Arrow Keys: Change Color\n\nCurrent Color: #{color_config[:name]}",
163
- block:,
164
- fg: style_config[:style] ? nil : color_config[:color],
165
- style: style_config[:style],
166
- alignment: :center
167
- )
168
-
169
- # Bottom control panel
170
- control_panel = @tui.block(
171
- title: "Controls",
172
- borders: [:all],
173
- children: [
174
- @tui.paragraph(
175
- text: [
176
- # Line 1: Main Controls
177
- @tui.text_line(spans: [
178
- @tui.text_span(content: "↑↓←→", style: @hotkey_style),
179
- @tui.text_span(content: ": Color (#{color_config[:name]}) "),
180
- @tui.text_span(content: "q", style: @hotkey_style),
181
- @tui.text_span(content: ": Quit"),
182
- ]),
183
- # Line 2: Borders
184
- @tui.text_line(spans: [
185
- @tui.text_span(content: "space", style: @hotkey_style),
186
- @tui.text_span(content: ": Border Type (#{type_display}) "),
187
- @tui.text_span(content: "c", style: @hotkey_style),
188
- @tui.text_span(content: ": Border Set (#{border_set_config[:name]})"),
189
- ]),
190
- # Line 3: Styles
191
- @tui.text_line(spans: [
192
- @tui.text_span(content: "s", style: @hotkey_style),
193
- @tui.text_span(content: ": Style (#{style_config[:name]}) "),
194
- @tui.text_span(content: "b", style: @hotkey_style),
195
- @tui.text_span(content: ": Border Style (#{border_style_config[:name]})"),
196
- ]),
197
- # Line 4: Title
198
- @tui.text_line(spans: [
199
- @tui.text_span(content: "enter", style: @hotkey_style),
200
- @tui.text_span(content: ": Align Title (#{title_alignment_config[:name]}) "),
201
- @tui.text_span(content: "t", style: @hotkey_style),
202
- @tui.text_span(content: ": Title Style (#{title_style_config[:name]})"),
203
- ]),
204
- ]
205
- ),
206
- ]
207
- )
208
-
209
- # 2. Render with Frame API
210
- @tui.draw do |frame|
211
- main_rect, control_rect = @tui.layout_split(
212
- frame.area,
213
- direction: :vertical,
214
- constraints: [
215
- @tui.constraint_fill(1),
216
- @tui.constraint_length(6),
217
- ]
218
- )
219
- frame.render_widget(main_panel, main_rect)
220
- frame.render_widget(control_panel, control_rect)
221
- end
222
- end
223
-
224
- private def handle_input
225
- # 3. Events
226
- case @tui.poll_event
227
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
228
- :quit
229
- in type: :key, code: "up"
230
- @color_index = (@color_index - 1) % @colors.size
231
- in type: :key, code: "down"
232
- @color_index = (@color_index + 1) % @colors.size
233
- in type: :key, code: "left"
234
- @color_index = (@color_index - 1) % @colors.size
235
- in type: :key, code: "right"
236
- @color_index = (@color_index + 1) % @colors.size
237
- in type: :key, code: " "
238
- @border_type_index = (@border_type_index + 1) % @border_types.size
239
- in type: :key, code: "c"
240
- @border_set_index = (@border_set_index + 1) % @border_sets.size
241
- in type: :key, code: "enter"
242
- @title_alignment_index = (@title_alignment_index + 1) % @title_alignments.size
243
- in type: :key, code: "s"
244
- @style_index = (@style_index + 1) % @styles.size
245
- in type: :key, code: "t"
246
- @title_style_index = (@title_style_index + 1) % @title_styles.size
247
- in type: :key, code: "b"
248
- @border_style_index = (@border_style_index + 1) % @border_styles.size
249
- else
250
- nil
251
- end
252
- end
253
- end
254
-
255
- WidgetBox.new.run if __FILE__ == $0
@@ -1,48 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Calendar Widget Example
7
-
8
- [![widget_calendar](../../doc/images/widget_calendar.png)](app.rb)
9
-
10
- Demonstrates a monthly calendar with customizable headers and event highlighting.
11
-
12
- Rendering dates in a grid involves complex calculations for leap years and weekday offsets. This widget handles that logic, letting you focus on displaying dates.
13
-
14
- ## Features Demonstrated
15
-
16
- - **Headers**: Toggling the Month name and Weekday labels.
17
- - **Surrounding Days**: displaying (or hiding/dimming) days from the previous and next months to fill the grid.
18
- - **Event Styling**: applying specific styles to individual `Time` or `Date` objects to highlight events.
19
-
20
- ## Hotkeys
21
-
22
- - **h**: Toggle Month Header (`show_month_header`)
23
- - **w**: Toggle Weekday Labels (`show_weekdays_header`)
24
- - **s**: Toggle Surrounding Days (`show_surrounding`)
25
- - **e**: Toggle Example Events (`events`)
26
- - **q**: Quit
27
-
28
- ## Usage
29
-
30
- <!-- SPDX-SnippetBegin -->
31
- <!--
32
- SPDX-FileCopyrightText: 2026 Kerrick Long
33
- SPDX-License-Identifier: MIT-0
34
- -->
35
- ```bash
36
- ruby examples/widget_calendar/app.rb
37
- ```
38
- <!-- SPDX-SnippetEnd -->
39
-
40
- ## Learning Outcomes
41
-
42
- Use this example if you need to...
43
-
44
- - Display a date picker.
45
- - Show a schedule or timeline view.
46
- - Highlight specific dates (deadlines, holidays) on a calendar grid.
47
-
48
- [Read the source code →](app.rb)
@@ -1,115 +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 monthly calendar attributes with interactive cycling.
12
- #
13
- # Dates are complex. Rendering them in a grid requires calculation of leap years, month lengths, and day-of-week offsets.
14
- # Use this widget to skip the boilerplate.
15
- #
16
- # This demo showcases the <tt>Calendar</tt> widget. It provides an interactive playground where you can toggle headers, weekday labels, and event highlights in real-time.
17
- #
18
- # Use it to understand how to render time-based data grids efficiently.
19
- #
20
- # === Example
21
- #
22
- # Run the demo from the terminal:
23
- #
24
- # ruby examples/widget_calendar/app.rb
25
- #
26
- # rdoc-image:/doc/images/widget_calendar.png
27
- class WidgetCalendar
28
- def initialize(date: nil)
29
- @date = date
30
- end
31
-
32
- def run
33
- RatatuiRuby.run do |tui|
34
- show_header = true
35
- show_weekdays = true
36
- show_surrounding = false
37
- show_events = true
38
- hotkey_style = tui.style(modifiers: [:bold])
39
-
40
- loop do
41
- now = @date || Time.now
42
- surrounding_style = show_surrounding ? tui.style(fg: "gray", modifiers: [:dim]) : nil
43
-
44
- events_map = if show_events
45
- {
46
- now => tui.style(fg: "green", modifiers: [:bold]),
47
- (now + (86400 * 2)) => tui.style(fg: "red", modifiers: [:underlined]),
48
- (now - (86400 * 5)) => tui.style(fg: "blue", bg: "white"),
49
- }
50
- else
51
- {}
52
- end
53
-
54
- calendar = tui.calendar(
55
- year: now.year,
56
- month: now.month,
57
- events: events_map,
58
- header_style: tui.style(fg: "yellow", modifiers: [:bold]),
59
- show_month_header: show_header,
60
- show_weekdays_header: show_weekdays,
61
- show_surrounding: surrounding_style,
62
- block: tui.block(borders: [:top, :left, :right])
63
- )
64
-
65
- controls = tui.paragraph(
66
- text: [
67
- tui.text_line(spans: [
68
- tui.text_span(content: " h/w/s/e", style: hotkey_style),
69
- tui.text_span(content: ": Toggle Header/Weekdays/Surrounding/Events "),
70
- tui.text_span(content: "q", style: hotkey_style),
71
- tui.text_span(content: ": Quit"),
72
- ]),
73
- tui.text_line(spans: [
74
- tui.text_span(content: " Events: ", style: hotkey_style),
75
- tui.text_span(content: "Today (Green), +2d (Red), -5d (Blue) (#{show_events ? 'On' : 'Off'})"),
76
- ]),
77
- ],
78
- block: tui.block(title: " Controls ", borders: [:all])
79
- )
80
-
81
- tui.draw do |frame|
82
- calendar_area, controls_area = tui.layout_split(
83
- frame.area,
84
- direction: :vertical,
85
- constraints: [
86
- tui.constraint_min(0),
87
- tui.constraint_length(4),
88
- ]
89
- )
90
- frame.render_widget(calendar, calendar_area)
91
- frame.render_widget(controls, controls_area)
92
- end
93
-
94
- case tui.poll_event
95
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
96
- break
97
- in type: :key, code: "h"
98
- show_header = !show_header
99
- in type: :key, code: "w"
100
- show_weekdays = !show_weekdays
101
- in type: :key, code: "s"
102
- show_surrounding = !show_surrounding
103
- in type: :key, code: "e"
104
- show_events = !show_events
105
- else
106
- nil
107
- end
108
-
109
- sleep 0.05
110
- end
111
- end
112
- end
113
- end
114
-
115
- WidgetCalendar.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,31 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
- # Canvas (Circle, Line, Point, Rectangle) Example
6
-
7
- [![widget_canvas](../../doc/images/widget_canvas.png)](app.rb)
8
-
9
- <!--
10
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
11
- SPDX-License-Identifier: CC-BY-SA-4.0
12
- -->
13
-
14
- This example demonstrates the `Canvas` widget, which provides a high-resolution drawing surface using Braille characters.
15
-
16
- ## Key Concepts
17
-
18
- - **Shapes**: Supports `Point`, `Line`, `Rectangle`, `Circle`, and `Map`.
19
- - **Coordinates**: Uses a float-based coordinate system independent of terminal cells.
20
- - **Markers**: Can use Braille (high res) or block characters (lower res) for rendering.
21
-
22
- ## Controls
23
-
24
- | Key | Action |
25
- | --- | --- |
26
- | `q` | Quit |
27
-
28
- ## Screenshot
29
- ## Source Code
30
-
31
- - [app.rb](app.rb)
@@ -1,130 +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
- # Canvas Widget
12
- # Demonstrates how to draw geometric shapes (Points, Lines, Rects, Circles)
13
- # on a high-resolution canvas.
14
- class WidgetCanvas
15
- def initialize
16
- @x_offset = 0.0
17
- @y_offset = 0.0
18
- @time = 0.0
19
- end
20
-
21
- def run
22
- RatatuiRuby.run do |tui|
23
- @tui = tui
24
- loop do
25
- # Animate
26
- @time += 0.1
27
- @x_offset = Math.sin(@time) * 20.0
28
- @y_offset = Math.cos(@time) * 20.0
29
-
30
- render
31
- break if handle_input == :quit
32
-
33
- sleep 0.05
34
- end
35
- end
36
- end
37
-
38
- private def render
39
- @tui.draw do |frame|
40
- # Define shapes using terse aliases (circle, rectangle, point, map, label)
41
- # These are shorter forms of shape_circle, shape_rectangle, etc.
42
- shapes = []
43
-
44
- # 1. Static Grid (Lines) - using shape_line (no terse alias for line)
45
- (-100..100).step(20) do |i|
46
- shapes << @tui.shape_line(x1: i.to_f, y1: -100.0, x2: i.to_f, y2: 100.0, color: :gray)
47
- shapes << @tui.shape_line(x1: -100.0, y1: i.to_f, x2: 100.0, y2: i.to_f, color: :gray)
48
- end
49
-
50
- # 2. Moving Circle (The "Player") - using terse 'circle' alias
51
- shapes << @tui.circle(
52
- x: @x_offset,
53
- y: @y_offset,
54
- radius: 10.0,
55
- color: :green
56
- )
57
-
58
- # 3. Static Rectangle (Target) - using shape_rectangle (no 'rectangle' alias
59
- # to avoid confusion with Layout::Rect)
60
- shapes << @tui.shape_rectangle(
61
- x: 30.0,
62
- y: 30.0,
63
- width: 20.0,
64
- height: 20.0,
65
- color: :red
66
- )
67
-
68
- # 4. Points (Starfield) - using terse 'point' alias
69
- # Deterministic "random" points
70
- 10.times do |i|
71
- shapes << @tui.point(
72
- x: ((i * 37) % 200) - 100.0,
73
- y: ((i * 19) % 200) - 100.0
74
- )
75
- end
76
-
77
- # 5. Connecting line from origin to player position
78
- shapes << @tui.shape_line(x1: 0.0, y1: 0.0, x2: @x_offset, y2: @y_offset, color: :yellow)
79
-
80
- canvas = @tui.canvas(
81
- shapes:,
82
- x_bounds: [-100.0, 100.0],
83
- y_bounds: [-100.0, 100.0],
84
- marker: :braille,
85
- block: @tui.block(title: "Canvas", borders: [:all])
86
- )
87
-
88
- # Main area for canvas
89
- layout = @tui.layout_split(
90
- frame.area,
91
- direction: :vertical,
92
- constraints: [
93
- @tui.constraint_fill(1),
94
- @tui.constraint_length(2),
95
- ]
96
- )
97
-
98
- frame.render_widget(canvas, layout[0])
99
-
100
- # Query: Canvas#get_point maps canvas coordinates to normalized [0.0, 1.0] grid
101
- normalized = canvas.get_point(@x_offset, @y_offset)
102
- norm_str = normalized ? format("[%.2f, %.2f]", normalized[0], normalized[1]) : "nil"
103
-
104
- # Controls showing query method demonstration (single concise line)
105
- controls = @tui.paragraph(
106
- text: [
107
- @tui.text_line(spans: [
108
- @tui.text_span(content: "q", style: @tui.style(modifiers: [:bold, :underlined])),
109
- @tui.text_span(content: ": Quit "),
110
- @tui.text_span(content: "get_point → ", style: @tui.style(fg: :dark_gray)),
111
- @tui.text_span(content: norm_str, style: @tui.style(fg: :cyan)),
112
- ]),
113
- ],
114
- block: @tui.block(borders: [:top])
115
- )
116
- frame.render_widget(controls, layout[1])
117
- end
118
- end
119
-
120
- def handle_input
121
- case @tui.poll_event
122
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
123
- :quit
124
- else
125
- # Ignore other events
126
- end
127
- end
128
- end
129
-
130
- WidgetCanvas.new.run if __FILE__ == $0
@@ -1,45 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Cell Widget Example
7
-
8
- [![widget_cell](../../doc/images/widget_cell.png)](app.rb)
9
-
10
- Demonstrates using `Cell` objects for granular control over individual character grid units.
11
-
12
- Sometimes you need to render specific characters with unique styles outside of standard widgets. The `Cell` primitive allows you to build custom widgets or inject styled content into Tables.
13
-
14
- ## Features Demonstrated
15
-
16
- - **Custom Widgets**: A `CheckeredBackground` widget built by rendering `Cell`s in a loop.
17
- - **Table Integration**: Mixing simple Strings and rich `Cell` objects in a Table row.
18
- - **Overlays**: Using `RatatuiRuby::Overlay` to stack widgets on top of each other.
19
- - **Modifiers**: Using `rapid_blink`, `bold`, and `dim` on individual cells.
20
-
21
- ## Hotkeys
22
-
23
- - **q** / **Ctrl+c**: Quit
24
-
25
- ## Usage
26
-
27
- <!-- SPDX-SnippetBegin -->
28
- <!--
29
- SPDX-FileCopyrightText: 2026 Kerrick Long
30
- SPDX-License-Identifier: MIT-0
31
- -->
32
- ```bash
33
- ruby examples/widget_cell/app.rb
34
- ```
35
- <!-- SPDX-SnippetEnd -->
36
-
37
- ## Learning Outcomes
38
-
39
- Use this example if you need to...
40
-
41
- - Create a custom widget (like a game board or specialized graph).
42
- - Style specific cells in a Table (e.g., Green "OK", Red "FAIL").
43
- - Understand how to position content precisely with `Cell`.
44
-
45
- [Read the source code →](app.rb)