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,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)