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