ratatui_ruby 0.4.0 → 0.6.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 (441) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +1 -1
  3. data/.builds/ruby-3.3.yml +1 -1
  4. data/.builds/ruby-3.4.yml +1 -1
  5. data/.builds/ruby-4.0.0.yml +1 -1
  6. data/AGENTS.md +98 -176
  7. data/CHANGELOG.md +80 -6
  8. data/README.md +19 -7
  9. data/REUSE.toml +15 -0
  10. data/doc/application_architecture.md +179 -45
  11. data/doc/application_testing.md +80 -32
  12. data/doc/contributors/design/ruby_frontend.md +48 -8
  13. data/doc/contributors/design/rust_backend.md +1 -0
  14. data/doc/contributors/developing_examples.md +191 -48
  15. data/doc/contributors/documentation_style.md +7 -0
  16. data/doc/contributors/examples_audit/p1_high.md +21 -0
  17. data/doc/contributors/examples_audit/p2_moderate.md +81 -0
  18. data/doc/contributors/examples_audit.md +41 -0
  19. data/doc/contributors/index.md +2 -0
  20. data/doc/event_handling.md +21 -7
  21. data/doc/images/app_all_events.png +0 -0
  22. data/doc/images/app_color_picker.png +0 -0
  23. data/doc/images/app_login_form.png +0 -0
  24. data/doc/images/app_stateful_interaction.png +0 -0
  25. data/doc/images/verify_quickstart_dsl.png +0 -0
  26. data/doc/images/verify_quickstart_layout.png +0 -0
  27. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  28. data/doc/images/verify_readme_usage.png +0 -0
  29. data/doc/images/widget_barchart_demo.png +0 -0
  30. data/doc/images/widget_block_demo.png +0 -0
  31. data/doc/images/widget_box_demo.png +0 -0
  32. data/doc/images/widget_calendar_demo.png +0 -0
  33. data/doc/images/widget_canvas_demo.png +0 -0
  34. data/doc/images/widget_cell_demo.png +0 -0
  35. data/doc/images/widget_center_demo.png +0 -0
  36. data/doc/images/widget_chart_demo.png +0 -0
  37. data/doc/images/widget_gauge_demo.png +0 -0
  38. data/doc/images/widget_layout_split.png +0 -0
  39. data/doc/images/widget_line_gauge_demo.png +0 -0
  40. data/doc/images/widget_list_demo.png +0 -0
  41. data/doc/images/widget_overlay_demo.png +0 -0
  42. data/doc/images/widget_ratatui_logo_demo.png +0 -0
  43. data/doc/images/widget_ratatui_mascot_demo.png +0 -0
  44. data/doc/images/widget_render.png +0 -0
  45. data/doc/images/widget_rich_text.png +0 -0
  46. data/doc/images/widget_scroll_text.png +0 -0
  47. data/doc/images/widget_scrollbar_demo.png +0 -0
  48. data/doc/images/widget_sparkline_demo.png +0 -0
  49. data/doc/images/widget_style_colors.png +0 -0
  50. data/doc/images/widget_table_demo.png +0 -0
  51. data/doc/images/widget_table_flex.png +0 -0
  52. data/doc/images/widget_tabs_demo.png +0 -0
  53. data/doc/images/widget_text_width.png +0 -0
  54. data/doc/interactive_design.md +25 -30
  55. data/doc/quickstart.md +150 -130
  56. data/doc/terminal_limitations.md +92 -0
  57. data/examples/app_all_events/README.md +99 -0
  58. data/examples/app_all_events/app.rb +96 -0
  59. data/examples/app_all_events/model/app_model.rb +157 -0
  60. data/examples/app_all_events/model/event_color_cycle.rb +41 -0
  61. data/examples/app_all_events/model/event_entry.rb +92 -0
  62. data/examples/app_all_events/model/msg.rb +37 -0
  63. data/examples/app_all_events/model/timestamp.rb +54 -0
  64. data/examples/app_all_events/update.rb +73 -0
  65. data/examples/app_all_events/view/app_view.rb +78 -0
  66. data/examples/app_all_events/view/controls_view.rb +52 -0
  67. data/examples/app_all_events/view/counts_view.rb +59 -0
  68. data/examples/app_all_events/view/live_view.rb +70 -0
  69. data/examples/app_all_events/view/log_view.rb +55 -0
  70. data/examples/app_all_events/view.rb +7 -0
  71. data/examples/app_color_picker/README.md +134 -0
  72. data/examples/app_color_picker/app.rb +74 -0
  73. data/examples/app_color_picker/clipboard.rb +84 -0
  74. data/examples/app_color_picker/color.rb +191 -0
  75. data/examples/app_color_picker/controls.rb +90 -0
  76. data/examples/app_color_picker/copy_dialog.rb +166 -0
  77. data/examples/app_color_picker/export_pane.rb +126 -0
  78. data/examples/app_color_picker/harmony.rb +56 -0
  79. data/examples/app_color_picker/input.rb +174 -0
  80. data/examples/app_color_picker/main_container.rb +178 -0
  81. data/examples/app_color_picker/palette.rb +109 -0
  82. data/examples/app_login_form/README.md +47 -0
  83. data/examples/{login_form → app_login_form}/app.rb +38 -42
  84. data/examples/app_stateful_interaction/README.md +31 -0
  85. data/examples/app_stateful_interaction/app.rb +272 -0
  86. data/examples/timeout_demo.rb +43 -0
  87. data/examples/verify_quickstart_dsl/README.md +48 -0
  88. data/examples/{quickstart_dsl → verify_quickstart_dsl}/app.rb +17 -6
  89. data/examples/verify_quickstart_layout/README.md +71 -0
  90. data/examples/verify_quickstart_layout/app.rb +71 -0
  91. data/examples/verify_quickstart_lifecycle/README.md +56 -0
  92. data/examples/verify_quickstart_lifecycle/app.rb +54 -0
  93. data/examples/verify_readme_usage/README.md +43 -0
  94. data/examples/verify_readme_usage/app.rb +40 -0
  95. data/examples/widget_barchart_demo/README.md +49 -0
  96. data/examples/widget_barchart_demo/app.rb +238 -0
  97. data/examples/widget_block_demo/README.md +34 -0
  98. data/examples/widget_block_demo/app.rb +256 -0
  99. data/examples/widget_box_demo/README.md +45 -0
  100. data/examples/{box_demo → widget_box_demo}/app.rb +99 -65
  101. data/examples/widget_calendar_demo/README.md +39 -0
  102. data/examples/widget_calendar_demo/app.rb +109 -0
  103. data/examples/widget_canvas_demo/README.md +27 -0
  104. data/examples/widget_canvas_demo/app.rb +123 -0
  105. data/examples/widget_cell_demo/README.md +36 -0
  106. data/examples/widget_cell_demo/app.rb +111 -0
  107. data/examples/widget_center_demo/README.md +29 -0
  108. data/examples/widget_center_demo/app.rb +116 -0
  109. data/examples/widget_chart_demo/README.md +41 -0
  110. data/examples/widget_chart_demo/app.rb +218 -0
  111. data/examples/widget_gauge_demo/README.md +41 -0
  112. data/examples/widget_gauge_demo/app.rb +212 -0
  113. data/examples/widget_layout_split/README.md +44 -0
  114. data/examples/widget_layout_split/app.rb +246 -0
  115. data/examples/widget_line_gauge_demo/README.md +41 -0
  116. data/examples/widget_line_gauge_demo/app.rb +217 -0
  117. data/examples/widget_list_demo/README.md +49 -0
  118. data/examples/widget_list_demo/app.rb +366 -0
  119. data/examples/widget_map_demo/README.md +39 -0
  120. data/examples/{map_demo → widget_map_demo}/app.rb +24 -21
  121. data/examples/widget_overlay_demo/app.rb +248 -0
  122. data/examples/widget_popup_demo/README.md +36 -0
  123. data/examples/widget_popup_demo/app.rb +104 -0
  124. data/examples/widget_ratatui_logo_demo/README.md +34 -0
  125. data/examples/widget_ratatui_logo_demo/app.rb +103 -0
  126. data/examples/widget_ratatui_mascot_demo/README.md +34 -0
  127. data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
  128. data/examples/widget_rect/README.md +38 -0
  129. data/examples/widget_rect/app.rb +205 -0
  130. data/examples/widget_render/README.md +37 -0
  131. data/examples/widget_render/app.rb +184 -0
  132. data/examples/widget_rich_text/README.md +35 -0
  133. data/examples/widget_rich_text/app.rb +166 -0
  134. data/examples/widget_scroll_text/README.md +37 -0
  135. data/examples/widget_scroll_text/app.rb +107 -0
  136. data/examples/widget_scrollbar_demo/README.md +37 -0
  137. data/examples/widget_scrollbar_demo/app.rb +153 -0
  138. data/examples/widget_sparkline_demo/README.md +42 -0
  139. data/examples/widget_sparkline_demo/app.rb +275 -0
  140. data/examples/widget_style_colors/README.md +34 -0
  141. data/examples/widget_style_colors/app.rb +19 -21
  142. data/examples/widget_table_demo/README.md +48 -0
  143. data/examples/widget_table_demo/app.rb +239 -0
  144. data/examples/widget_tabs_demo/README.md +41 -0
  145. data/examples/widget_tabs_demo/app.rb +181 -0
  146. data/examples/widget_text_width/README.md +35 -0
  147. data/examples/widget_text_width/app.rb +106 -0
  148. data/ext/ratatui_ruby/Cargo.lock +11 -4
  149. data/ext/ratatui_ruby/Cargo.toml +2 -1
  150. data/ext/ratatui_ruby/src/events.rs +359 -62
  151. data/ext/ratatui_ruby/src/frame.rs +227 -0
  152. data/ext/ratatui_ruby/src/lib.rs +110 -27
  153. data/ext/ratatui_ruby/src/rendering.rs +8 -4
  154. data/ext/ratatui_ruby/src/string_width.rs +101 -0
  155. data/ext/ratatui_ruby/src/style.rs +138 -57
  156. data/ext/ratatui_ruby/src/terminal.rs +42 -22
  157. data/ext/ratatui_ruby/src/text.rs +14 -7
  158. data/ext/ratatui_ruby/src/widgets/barchart.rs +74 -54
  159. data/ext/ratatui_ruby/src/widgets/block.rs +7 -6
  160. data/ext/ratatui_ruby/src/widgets/canvas.rs +21 -3
  161. data/ext/ratatui_ruby/src/widgets/chart.rs +20 -10
  162. data/ext/ratatui_ruby/src/widgets/gauge.rs +9 -2
  163. data/ext/ratatui_ruby/src/widgets/layout.rs +9 -4
  164. data/ext/ratatui_ruby/src/widgets/line_gauge.rs +9 -2
  165. data/ext/ratatui_ruby/src/widgets/list.rs +211 -12
  166. data/ext/ratatui_ruby/src/widgets/list_state.rs +137 -0
  167. data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
  168. data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
  169. data/ext/ratatui_ruby/src/widgets/paragraph.rs +1 -1
  170. data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +19 -8
  171. data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +17 -10
  172. data/ext/ratatui_ruby/src/widgets/scrollbar.rs +97 -3
  173. data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
  174. data/ext/ratatui_ruby/src/widgets/sparkline.rs +14 -11
  175. data/ext/ratatui_ruby/src/widgets/table.rs +121 -5
  176. data/ext/ratatui_ruby/src/widgets/table_state.rs +121 -0
  177. data/ext/ratatui_ruby/src/widgets/tabs.rs +11 -11
  178. data/lib/ratatui_ruby/cell.rb +7 -7
  179. data/lib/ratatui_ruby/event/key/character.rb +35 -0
  180. data/lib/ratatui_ruby/event/key/media.rb +44 -0
  181. data/lib/ratatui_ruby/event/key/modifier.rb +95 -0
  182. data/lib/ratatui_ruby/event/key/navigation.rb +55 -0
  183. data/lib/ratatui_ruby/event/key/system.rb +45 -0
  184. data/lib/ratatui_ruby/event/key.rb +112 -52
  185. data/lib/ratatui_ruby/event/mouse.rb +3 -3
  186. data/lib/ratatui_ruby/event/none.rb +43 -0
  187. data/lib/ratatui_ruby/event/paste.rb +1 -1
  188. data/lib/ratatui_ruby/event.rb +56 -4
  189. data/lib/ratatui_ruby/frame.rb +183 -0
  190. data/lib/ratatui_ruby/list_state.rb +88 -0
  191. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +13 -13
  192. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +1 -5
  193. data/lib/ratatui_ruby/schema/bar_chart.rb +217 -217
  194. data/lib/ratatui_ruby/schema/block.rb +163 -168
  195. data/lib/ratatui_ruby/schema/calendar.rb +66 -67
  196. data/lib/ratatui_ruby/schema/canvas.rb +63 -63
  197. data/lib/ratatui_ruby/schema/center.rb +46 -46
  198. data/lib/ratatui_ruby/schema/chart.rb +135 -143
  199. data/lib/ratatui_ruby/schema/clear.rb +42 -42
  200. data/lib/ratatui_ruby/schema/constraint.rb +76 -76
  201. data/lib/ratatui_ruby/schema/cursor.rb +30 -25
  202. data/lib/ratatui_ruby/schema/gauge.rb +54 -52
  203. data/lib/ratatui_ruby/schema/layout.rb +87 -87
  204. data/lib/ratatui_ruby/schema/line_gauge.rb +62 -62
  205. data/lib/ratatui_ruby/schema/list.rb +103 -80
  206. data/lib/ratatui_ruby/schema/list_item.rb +41 -0
  207. data/lib/ratatui_ruby/schema/overlay.rb +31 -31
  208. data/lib/ratatui_ruby/schema/paragraph.rb +80 -80
  209. data/lib/ratatui_ruby/schema/ratatui_logo.rb +10 -6
  210. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +10 -5
  211. data/lib/ratatui_ruby/schema/rect.rb +99 -56
  212. data/lib/ratatui_ruby/schema/scrollbar.rb +119 -119
  213. data/lib/ratatui_ruby/schema/shape/label.rb +1 -1
  214. data/lib/ratatui_ruby/schema/sparkline.rb +111 -110
  215. data/lib/ratatui_ruby/schema/style.rb +66 -46
  216. data/lib/ratatui_ruby/schema/table.rb +126 -115
  217. data/lib/ratatui_ruby/schema/tabs.rb +66 -67
  218. data/lib/ratatui_ruby/schema/text.rb +69 -1
  219. data/lib/ratatui_ruby/scrollbar_state.rb +112 -0
  220. data/lib/ratatui_ruby/session/autodoc.rb +482 -0
  221. data/lib/ratatui_ruby/session.rb +55 -23
  222. data/lib/ratatui_ruby/table_state.rb +90 -0
  223. data/lib/ratatui_ruby/test_helper/event_injection.rb +169 -0
  224. data/lib/ratatui_ruby/test_helper/snapshot.rb +390 -0
  225. data/lib/ratatui_ruby/test_helper/style_assertions.rb +351 -0
  226. data/lib/ratatui_ruby/test_helper/terminal.rb +127 -0
  227. data/lib/ratatui_ruby/test_helper/test_doubles.rb +68 -0
  228. data/lib/ratatui_ruby/test_helper.rb +66 -193
  229. data/lib/ratatui_ruby/version.rb +1 -1
  230. data/lib/ratatui_ruby.rb +100 -51
  231. data/{examples/sparkline_demo → sig/examples/app_all_events}/app.rbs +3 -2
  232. data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
  233. data/sig/examples/app_all_events/model/events.rbs +15 -0
  234. data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
  235. data/sig/examples/app_all_events/view/app_view.rbs +8 -0
  236. data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
  237. data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
  238. data/sig/examples/app_all_events/view/live_view.rbs +6 -0
  239. data/sig/examples/app_all_events/view/log_view.rbs +6 -0
  240. data/sig/examples/app_all_events/view.rbs +8 -0
  241. data/sig/examples/app_all_events/view_state.rbs +15 -0
  242. data/{examples/list_demo → sig/examples/app_color_picker}/app.rbs +2 -2
  243. data/sig/examples/app_login_form/app.rbs +11 -0
  244. data/sig/examples/app_stateful_interaction/app.rbs +33 -0
  245. data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
  246. data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
  247. data/sig/examples/verify_readme_usage/app.rbs +11 -0
  248. data/sig/examples/widget_block_demo/app.rbs +32 -0
  249. data/sig/examples/widget_box_demo/app.rbs +11 -0
  250. data/sig/examples/widget_calendar_demo/app.rbs +11 -0
  251. data/sig/examples/widget_cell_demo/app.rbs +11 -0
  252. data/sig/examples/widget_chart_demo/app.rbs +11 -0
  253. data/{examples/gauge_demo → sig/examples/widget_gauge_demo}/app.rbs +4 -0
  254. data/sig/examples/widget_layout_split/app.rbs +10 -0
  255. data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
  256. data/sig/examples/widget_list_demo/app.rbs +12 -0
  257. data/sig/examples/widget_map_demo/app.rbs +11 -0
  258. data/sig/examples/widget_popup_demo/app.rbs +11 -0
  259. data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
  260. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
  261. data/sig/examples/widget_rect/app.rbs +12 -0
  262. data/sig/examples/widget_render/app.rbs +10 -0
  263. data/sig/examples/widget_rich_text/app.rbs +11 -0
  264. data/sig/examples/widget_scroll_text/app.rbs +11 -0
  265. data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
  266. data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
  267. data/{examples → sig/examples}/widget_style_colors/app.rbs +1 -1
  268. data/sig/examples/widget_table_demo/app.rbs +11 -0
  269. data/sig/examples/widget_text_width/app.rbs +10 -0
  270. data/sig/ratatui_ruby/event.rbs +11 -1
  271. data/sig/ratatui_ruby/frame.rbs +11 -0
  272. data/sig/ratatui_ruby/list_state.rbs +13 -0
  273. data/sig/ratatui_ruby/ratatui_ruby.rbs +5 -4
  274. data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +3 -3
  275. data/sig/ratatui_ruby/schema/draw.rbs +4 -0
  276. data/sig/ratatui_ruby/schema/gauge.rbs +2 -2
  277. data/sig/ratatui_ruby/schema/layout.rbs +1 -1
  278. data/sig/ratatui_ruby/schema/line_gauge.rbs +2 -2
  279. data/sig/ratatui_ruby/schema/list.rbs +4 -2
  280. data/sig/ratatui_ruby/schema/list_item.rbs +10 -0
  281. data/sig/ratatui_ruby/schema/rect.rbs +3 -0
  282. data/sig/ratatui_ruby/schema/style.rbs +3 -3
  283. data/sig/ratatui_ruby/schema/table.rbs +3 -1
  284. data/sig/ratatui_ruby/schema/text.rbs +8 -6
  285. data/sig/ratatui_ruby/scrollbar_state.rbs +18 -0
  286. data/sig/ratatui_ruby/session.rbs +107 -0
  287. data/sig/ratatui_ruby/table_state.rbs +15 -0
  288. data/sig/ratatui_ruby/test_helper/event_injection.rbs +16 -0
  289. data/sig/ratatui_ruby/test_helper/snapshot.rbs +12 -0
  290. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +64 -0
  291. data/sig/ratatui_ruby/test_helper/terminal.rbs +14 -0
  292. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +22 -0
  293. data/sig/ratatui_ruby/test_helper.rbs +5 -4
  294. data/tasks/autodoc/examples.rb +79 -0
  295. data/tasks/autodoc/inventory.rb +63 -0
  296. data/tasks/autodoc/member.rb +56 -0
  297. data/tasks/autodoc/name.rb +19 -0
  298. data/tasks/autodoc/notice.rb +26 -0
  299. data/tasks/autodoc/rbs.rb +38 -0
  300. data/tasks/autodoc/rdoc.rb +45 -0
  301. data/tasks/autodoc.rake +53 -0
  302. data/tasks/bump/changelog.rb +3 -3
  303. data/tasks/bump/history.rb +2 -2
  304. data/tasks/bump/links.rb +67 -0
  305. data/tasks/doc.rake +600 -6
  306. data/tasks/example_viewer.html.erb +172 -0
  307. data/tasks/lint.rake +8 -4
  308. data/tasks/resources/index.html.erb +6 -0
  309. data/tasks/sourcehut.rake +70 -30
  310. data/tasks/terminal_preview/app_screenshot.rb +14 -6
  311. data/tasks/terminal_preview/crash_report.rb +7 -9
  312. data/tasks/terminal_preview/launcher_script.rb +4 -6
  313. data/tasks/terminal_preview/preview_collection.rb +4 -6
  314. data/tasks/terminal_preview/safety_confirmation.rb +3 -5
  315. data/tasks/terminal_preview/saved_screenshot.rb +10 -11
  316. data/tasks/terminal_preview/terminal_window.rb +7 -9
  317. data/tasks/test.rake +1 -1
  318. data/tasks/website/index_page.rb +3 -3
  319. data/tasks/website/version.rb +10 -10
  320. data/tasks/website/version_menu.rb +10 -12
  321. data/tasks/website/versioned_documentation.rb +49 -17
  322. data/tasks/website/website.rb +6 -8
  323. data/tasks/website.rake +4 -4
  324. metadata +232 -127
  325. data/LICENSES/BSD-2-Clause.txt +0 -9
  326. data/doc/contributors/better_dx.md +0 -543
  327. data/doc/contributors/example_analysis.md +0 -82
  328. data/doc/images/all_events.png +0 -0
  329. data/doc/images/block_padding.png +0 -0
  330. data/doc/images/block_titles.png +0 -0
  331. data/doc/images/box_demo.png +0 -0
  332. data/doc/images/calendar_demo.png +0 -0
  333. data/doc/images/cell_demo.png +0 -0
  334. data/doc/images/chart_demo.png +0 -0
  335. data/doc/images/flex_layout.png +0 -0
  336. data/doc/images/gauge_demo.png +0 -0
  337. data/doc/images/line_gauge_demo.png +0 -0
  338. data/doc/images/list_demo.png +0 -0
  339. data/doc/images/list_styles.png +0 -0
  340. data/doc/images/login_form.png +0 -0
  341. data/doc/images/quickstart_dsl.png +0 -0
  342. data/doc/images/quickstart_lifecycle.png +0 -0
  343. data/doc/images/readme_usage.png +0 -0
  344. data/doc/images/rich_text.png +0 -0
  345. data/doc/images/scroll_text.png +0 -0
  346. data/doc/images/scrollbar_demo.png +0 -0
  347. data/doc/images/sparkline_demo.png +0 -0
  348. data/doc/images/table_flex.png +0 -0
  349. data/doc/images/table_select.png +0 -0
  350. data/examples/all_events/app.rb +0 -169
  351. data/examples/all_events/app.rbs +0 -7
  352. data/examples/all_events/test_app.rb +0 -139
  353. data/examples/analytics/app.rb +0 -258
  354. data/examples/analytics/app.rbs +0 -7
  355. data/examples/analytics/test_app.rb +0 -132
  356. data/examples/block_padding/app.rb +0 -63
  357. data/examples/block_padding/app.rbs +0 -7
  358. data/examples/block_padding/test_app.rb +0 -31
  359. data/examples/block_titles/app.rb +0 -61
  360. data/examples/block_titles/app.rbs +0 -7
  361. data/examples/block_titles/test_app.rb +0 -34
  362. data/examples/box_demo/app.rbs +0 -7
  363. data/examples/box_demo/test_app.rb +0 -88
  364. data/examples/calendar_demo/app.rb +0 -101
  365. data/examples/calendar_demo/app.rbs +0 -7
  366. data/examples/calendar_demo/test_app.rb +0 -108
  367. data/examples/cell_demo/app.rb +0 -108
  368. data/examples/cell_demo/app.rbs +0 -7
  369. data/examples/cell_demo/test_app.rb +0 -36
  370. data/examples/chart_demo/app.rb +0 -203
  371. data/examples/chart_demo/app.rbs +0 -7
  372. data/examples/chart_demo/test_app.rb +0 -102
  373. data/examples/custom_widget/app.rb +0 -51
  374. data/examples/custom_widget/app.rbs +0 -7
  375. data/examples/custom_widget/test_app.rb +0 -30
  376. data/examples/flex_layout/app.rb +0 -156
  377. data/examples/flex_layout/app.rbs +0 -7
  378. data/examples/flex_layout/test_app.rb +0 -65
  379. data/examples/gauge_demo/app.rb +0 -182
  380. data/examples/gauge_demo/test_app.rb +0 -120
  381. data/examples/hit_test/app.rb +0 -175
  382. data/examples/hit_test/app.rbs +0 -7
  383. data/examples/hit_test/test_app.rb +0 -102
  384. data/examples/line_gauge_demo/app.rb +0 -190
  385. data/examples/line_gauge_demo/app.rbs +0 -7
  386. data/examples/line_gauge_demo/test_app.rb +0 -129
  387. data/examples/list_demo/app.rb +0 -253
  388. data/examples/list_demo/test_app.rb +0 -237
  389. data/examples/list_styles/app.rb +0 -140
  390. data/examples/list_styles/app.rbs +0 -7
  391. data/examples/list_styles/test_app.rb +0 -157
  392. data/examples/login_form/app.rbs +0 -7
  393. data/examples/login_form/test_app.rb +0 -51
  394. data/examples/map_demo/app.rbs +0 -7
  395. data/examples/map_demo/test_app.rb +0 -149
  396. data/examples/mouse_events/app.rb +0 -97
  397. data/examples/mouse_events/app.rbs +0 -7
  398. data/examples/mouse_events/test_app.rb +0 -53
  399. data/examples/popup_demo/app.rb +0 -103
  400. data/examples/popup_demo/app.rbs +0 -7
  401. data/examples/popup_demo/test_app.rb +0 -54
  402. data/examples/quickstart_dsl/app.rbs +0 -7
  403. data/examples/quickstart_dsl/test_app.rb +0 -29
  404. data/examples/quickstart_lifecycle/app.rb +0 -39
  405. data/examples/quickstart_lifecycle/app.rbs +0 -7
  406. data/examples/quickstart_lifecycle/test_app.rb +0 -29
  407. data/examples/ratatui_logo_demo/app.rb +0 -79
  408. data/examples/ratatui_logo_demo/app.rbs +0 -7
  409. data/examples/ratatui_logo_demo/test_app.rb +0 -51
  410. data/examples/ratatui_mascot_demo/app.rb +0 -84
  411. data/examples/ratatui_mascot_demo/app.rbs +0 -7
  412. data/examples/ratatui_mascot_demo/test_app.rb +0 -47
  413. data/examples/readme_usage/app.rb +0 -29
  414. data/examples/readme_usage/app.rbs +0 -7
  415. data/examples/readme_usage/test_app.rb +0 -29
  416. data/examples/rich_text/app.rb +0 -141
  417. data/examples/rich_text/app.rbs +0 -7
  418. data/examples/rich_text/test_app.rb +0 -166
  419. data/examples/scroll_text/app.rb +0 -103
  420. data/examples/scroll_text/app.rbs +0 -7
  421. data/examples/scroll_text/test_app.rb +0 -110
  422. data/examples/scrollbar_demo/app.rb +0 -143
  423. data/examples/scrollbar_demo/app.rbs +0 -7
  424. data/examples/scrollbar_demo/test_app.rb +0 -77
  425. data/examples/sparkline_demo/app.rb +0 -240
  426. data/examples/sparkline_demo/test_app.rb +0 -107
  427. data/examples/table_flex/app.rb +0 -65
  428. data/examples/table_flex/app.rbs +0 -7
  429. data/examples/table_flex/test_app.rb +0 -36
  430. data/examples/table_select/app.rb +0 -198
  431. data/examples/table_select/app.rbs +0 -7
  432. data/examples/table_select/test_app.rb +0 -180
  433. data/examples/widget_style_colors/test_app.rb +0 -48
  434. data/tasks/bump/comparison_links.rb +0 -41
  435. /data/doc/images/{analytics.png → app_analytics.png} +0 -0
  436. /data/doc/images/{custom_widget.png → app_custom_widget.png} +0 -0
  437. /data/doc/images/{mouse_events.png → app_mouse_events.png} +0 -0
  438. /data/doc/images/{map_demo.png → widget_map_demo.png} +0 -0
  439. /data/doc/images/{popup_demo.png → widget_popup_demo.png} +0 -0
  440. /data/doc/images/{hit_test.png → widget_rect.png} +0 -0
  441. /data/{doc/images/ratatui_logo_demo.png → exe/.gitkeep} +0 -0
@@ -7,7 +7,7 @@ $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
7
  require "ratatui_ruby"
8
8
 
9
9
  # An example of the Canvas widget showing a world map and animated shapes.
10
- class MapDemoApp
10
+ class WidgetMapDemo
11
11
  include RatatuiRuby
12
12
 
13
13
  COLORS = [:black, :blue, :white, nil].freeze
@@ -15,40 +15,41 @@ class MapDemoApp
15
15
 
16
16
  # Returns a Canvas view for the map demo with the given circle radius.
17
17
  #
18
+ # +tui+:: The RatatuiRuby::Session instance.
18
19
  # +radius+:: The radius of the animated circle.
19
20
  # +marker+:: The marker type.
20
21
  # +background_color+:: The background color of the canvas.
21
22
  # +show_labels+:: Whether to show city labels.
22
- def view(radius, marker = :braille, background_color = nil, show_labels: true)
23
+ def view(tui, radius, marker = :braille, background_color = nil, show_labels: true)
23
24
  shapes = [
24
- Shape::Map.new(color: :green, resolution: :high),
25
- Shape::Circle.new(x: 0.0, y: 0.0, radius:, color: :red),
26
- Shape::Line.new(x1: 0.0, y1: 0.0, x2: 50.0, y2: 25.0, color: :yellow),
25
+ tui.shape_map(color: :green, resolution: :high),
26
+ tui.shape_circle(x: 0.0, y: 0.0, radius:, color: :red),
27
+ tui.shape_line(x1: 0.0, y1: 0.0, x2: 50.0, y2: 25.0, color: :yellow),
27
28
  ]
28
29
 
29
30
  if show_labels
30
31
  shapes += [
31
- Shape::Label.new(x: -0.1, y: 51.5, text: "London", style: Style.new(fg: :cyan)),
32
- Shape::Label.new(x: 139.7, y: 35.7, text: "Tokyo", style: Style.new(fg: :magenta)),
33
- Shape::Label.new(x: -74.0, y: 40.7, text: "New York", style: Style.new(fg: :yellow)),
34
- Shape::Label.new(x: -122.4, y: 37.8, text: "San Francisco", style: Style.new(fg: :blue)),
35
- Shape::Label.new(x: 151.2, y: -33.9, text: "Sydney", style: Style.new(fg: :green)),
32
+ tui.shape_label(x: -0.1, y: 51.5, text: "London", style: tui.style(fg: :cyan)),
33
+ tui.shape_label(x: 139.7, y: 35.7, text: "Tokyo", style: tui.style(fg: :magenta)),
34
+ tui.shape_label(x: -74.0, y: 40.7, text: "New York", style: tui.style(fg: :yellow)),
35
+ tui.shape_label(x: -122.4, y: 37.8, text: "San Francisco", style: tui.style(fg: :blue)),
36
+ tui.shape_label(x: 151.2, y: -33.9, text: "Sydney", style: tui.style(fg: :green)),
36
37
  ]
37
38
  end
38
39
 
39
- Canvas.new(
40
- shapes: shapes,
40
+ tui.canvas(
41
+ shapes:,
41
42
  x_bounds: [-180.0, 180.0],
42
43
  y_bounds: [-90.0, 90.0],
43
- marker: marker,
44
- block: Block.new(title: "World Map ['b' bg, 'm' marker: #{marker}, 'l' labels: #{show_labels ? 'on' : 'off'}]", borders: :all),
45
- background_color: background_color
44
+ marker:,
45
+ block: tui.block(title: "World Map ['b' bg, 'm' marker: #{marker}, 'l' labels: #{show_labels ? 'on' : 'off'}]", borders: :all),
46
+ background_color:
46
47
  )
47
48
  end
48
49
 
49
50
  # Runs the map demo loop.
50
51
  def run
51
- RatatuiRuby.run do
52
+ RatatuiRuby.run do |tui|
52
53
  radius = 0.0
53
54
  direction = 1
54
55
  bg_index = 0
@@ -63,13 +64,15 @@ class MapDemoApp
63
64
  end
64
65
 
65
66
  # Define the view
66
- v = view(radius, MARKERS[marker_index], COLORS[bg_index], show_labels:)
67
+ canvas = view(tui, radius, MARKERS[marker_index], COLORS[bg_index], show_labels:)
67
68
 
68
- RatatuiRuby.draw(v)
69
+ tui.draw do |frame|
70
+ frame.render_widget(canvas, frame.area)
71
+ end
69
72
 
70
- event = RatatuiRuby.poll_event
73
+ event = tui.poll_event
71
74
  case event
72
- in {type: :key, code: "q"} | {type: :key, code: :ctrl_c}
75
+ in { type: :key, code: "q" } | { type: :key, code: :ctrl_c }
73
76
  break
74
77
  in type: :key, code: "b"
75
78
  bg_index = (bg_index + 1) % COLORS.size
@@ -87,4 +90,4 @@ class MapDemoApp
87
90
  end
88
91
  end
89
92
 
90
- MapDemoApp.new.run if __FILE__ == $PROGRAM_NAME
93
+ WidgetMapDemo.new.run if __FILE__ == $PROGRAM_NAME
@@ -0,0 +1,248 @@
1
+ # frozen_string_literal: true
2
+
3
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-License-Identifier: AGPL-3.0-or-later
5
+
6
+ $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
+ require "ratatui_ruby"
8
+
9
+ HEADLINES = [
10
+ "Scientists Discover New Species of Deep-Sea Octopus Near Hawaii",
11
+ "Global Climate Summit Reaches Historic Agreement on Emissions",
12
+ "Tech Giant Announces Breakthrough in Quantum Computing Research",
13
+ "Local Community Garden Initiative Expands to Ten More Cities",
14
+ "Astronomers Detect Unusual Radio Signals from Distant Galaxy",
15
+ "New Study Links Mediterranean Diet to Improved Heart Health",
16
+ "Electric Vehicle Sales Surge as Battery Technology Improves",
17
+ "Ancient Manuscripts Reveal Previously Unknown Trading Routes",
18
+ "Renewable Energy Now Powers 40% of National Grid",
19
+ "Robotics Team Develops AI System for Disaster Response",
20
+ "Archaeological Dig Uncovers Evidence of Early Human Settlement",
21
+ "Major Airline Commits to Carbon-Neutral Flights by 2035",
22
+ "Breakthrough Treatment Shows Promise for Rare Genetic Disease",
23
+ "City Council Approves Expanded Public Transportation Network",
24
+ "Marine Biologists Track Migration Patterns of Endangered Whales",
25
+ "New App Helps Farmers Optimize Water Usage During Drought",
26
+ "International Space Station Extends Mission Timeline to 2030",
27
+ "Local Schools Implement Innovative STEM Education Program",
28
+ "Wildlife Conservation Efforts Lead to Species Population Recovery",
29
+ "Research Team Creates Biodegradable Alternative to Plastic Packaging",
30
+ "Historic Theater Restoration Project Nears Completion",
31
+ "Cybersecurity Experts Warn of Emerging Online Threats",
32
+ "Community Food Bank Serves Record Number of Families This Year",
33
+ "Innovative Urban Planning Reduces Traffic Congestion by 30%",
34
+ ].freeze
35
+
36
+ # Overlay Demo Example
37
+ # Demonstrates the Overlay widget for layering widgets with depth.
38
+ class WidgetOverlayDemo
39
+ def initialize
40
+ @layer_count = 2 # Start with 2 layers visible
41
+ @swapped = false
42
+ @clear = true
43
+ end
44
+
45
+ def run
46
+ RatatuiRuby.run do |tui|
47
+ @tui = tui
48
+ loop do
49
+ tui.draw do |frame|
50
+ render(frame)
51
+ end
52
+ break if handle_input == :quit
53
+ sleep 0.05
54
+ end
55
+ end
56
+ end
57
+
58
+ private def render(frame)
59
+ area = frame.area
60
+
61
+ # Split into main area and control panel
62
+ layout = @tui.layout_split(
63
+ area,
64
+ direction: :vertical,
65
+ constraints: [
66
+ @tui.constraint_fill(1),
67
+ @tui.constraint_length(5),
68
+ ]
69
+ )
70
+
71
+ main_area = layout[0]
72
+ control_area = layout[1]
73
+
74
+ # Render background layer - RSS reader
75
+ frame.render_widget(background_layer, main_area)
76
+
77
+ # Render upper layers based on layer_count and swap state
78
+ if @swapped
79
+ render_beta_layer(frame, main_area) if @layer_count >= 2
80
+ render_notification_layer(frame, main_area) if @layer_count >= 1
81
+ else
82
+ render_notification_layer(frame, main_area) if @layer_count >= 1
83
+ render_beta_layer(frame, main_area) if @layer_count >= 2
84
+ end
85
+
86
+ # Render control panel
87
+ frame.render_widget(control_panel, control_area)
88
+ end
89
+
90
+ def background_layer
91
+ @background_layer ||= @tui.list(
92
+ items: HEADLINES,
93
+ block: @tui.block(
94
+ title: "RSS Reader",
95
+ borders: [:all]
96
+ )
97
+ )
98
+ end
99
+
100
+ def render_notification_layer(frame, area)
101
+ # Position modal: 20% from top, 60% height, 15% from left, 70% width
102
+
103
+ vertical_sections = @tui.layout_split(
104
+ area,
105
+ direction: :vertical,
106
+ constraints: [
107
+ @tui.constraint_fill(2),
108
+ @tui.constraint_fill(5),
109
+ @tui.constraint_fill(3),
110
+ ]
111
+ )
112
+
113
+ horizontal_sections = @tui.layout_split(
114
+ vertical_sections[1],
115
+ direction: :horizontal,
116
+ constraints: [
117
+ @tui.constraint_fill(1),
118
+ @tui.constraint_fill(5),
119
+ @tui.constraint_fill(1),
120
+ ]
121
+ )
122
+
123
+ modal_rect = horizontal_sections[1]
124
+
125
+ frame.render_widget(@tui.clear, modal_rect) if @clear
126
+
127
+ # Render the modal content
128
+ frame.render_widget(
129
+ @tui.paragraph(
130
+ text: "Your feeds have been updated",
131
+ wrap: true,
132
+ alignment: :center,
133
+ block: @tui.block(
134
+ title: "Notification",
135
+ borders: [:all],
136
+ border_style: @tui.style(fg: :black),
137
+ style: @tui.style(bg: :red, fg: :black)
138
+ )
139
+ ),
140
+ modal_rect
141
+ )
142
+ end
143
+
144
+ def render_beta_layer(frame, area)
145
+ # Position modal: 30% from top, 40% height, 25% from left, 50% width
146
+
147
+ vertical_sections = @tui.layout_split(
148
+ area,
149
+ direction: :vertical,
150
+ constraints: [
151
+ @tui.constraint_fill(3),
152
+ @tui.constraint_fill(4),
153
+ @tui.constraint_fill(2),
154
+ ]
155
+ )
156
+
157
+ horizontal_sections = @tui.layout_split(
158
+ vertical_sections[1],
159
+ direction: :horizontal,
160
+ constraints: [
161
+ @tui.constraint_fill(2),
162
+ @tui.constraint_fill(3),
163
+ @tui.constraint_fill(2),
164
+ ]
165
+ )
166
+
167
+ modal_rect = horizontal_sections[1]
168
+
169
+ frame.render_widget(@tui.clear, modal_rect) if @clear
170
+
171
+ # Render the modal content
172
+ frame.render_widget(
173
+ beta_paragraph,
174
+ modal_rect
175
+ )
176
+ end
177
+
178
+ def beta_paragraph
179
+ @beta_paragraph ||= @tui.paragraph(
180
+ text: "Thank you for being a beta tester. To give feedback, shout very loudly and we will hear you. Be careful not to scare the llamas.",
181
+ wrap: true,
182
+ alignment: :left,
183
+ block: @tui.block(
184
+ title: "Beta Program",
185
+ borders: [:all],
186
+ border_style: @tui.style(fg: :black),
187
+ style: @tui.style(bg: :blue, fg: :black)
188
+ )
189
+ )
190
+ end
191
+
192
+ def control_panel
193
+ bold_underline = @tui.style(modifiers: [:bold, :underlined])
194
+
195
+ first_controls = [
196
+ @tui.text_span(content: "0", style: bold_underline),
197
+ @tui.text_span(content: "/"),
198
+ @tui.text_span(content: "1", style: bold_underline),
199
+ @tui.text_span(content: "/"),
200
+ @tui.text_span(content: "2", style: bold_underline),
201
+ @tui.text_span(content: ": Change number of overlays | "),
202
+ @tui.text_span(content: "space", style: bold_underline),
203
+ @tui.text_span(content: ": Swap overlay order"),
204
+ ]
205
+ second_controls = [
206
+ @tui.text_span(content: "c", style: bold_underline),
207
+ @tui.text_span(content: ": Toggle clear (currently #{@clear ? 'on' : 'off'})"),
208
+ ]
209
+ third_controls = [
210
+ @tui.text_span(content: "q", style: bold_underline),
211
+ @tui.text_span(content: ": Quit"),
212
+ ]
213
+
214
+ first = @tui.text_line(spans: first_controls)
215
+ second = @tui.text_line(spans: second_controls)
216
+ third = @tui.text_line(spans: third_controls)
217
+
218
+ @tui.paragraph(
219
+ text: [first, second, third],
220
+ alignment: :center,
221
+ block: @tui.block(
222
+ title: "Controls",
223
+ borders: [:all]
224
+ )
225
+ )
226
+ end
227
+
228
+ def handle_input
229
+ case @tui.poll_event
230
+ in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
231
+ :quit
232
+ in { type: :key, code: "0" }
233
+ @layer_count = 0
234
+ in { type: :key, code: "1" }
235
+ @layer_count = 1
236
+ in { type: :key, code: "2" }
237
+ @layer_count = 2
238
+ in { type: :key, code: " " }
239
+ @swapped = !@swapped
240
+ in { type: :key, code: "c" }
241
+ @clear = !@clear
242
+ else
243
+ nil
244
+ end
245
+ end
246
+ end
247
+
248
+ WidgetOverlayDemo.new.run if __FILE__ == $PROGRAM_NAME
@@ -0,0 +1,36 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Popup (Clear) Widget Example
7
+
8
+ Demonstrates how to render opaque overlays on top of content.
9
+
10
+ Terminal renders are additive. If you draw a new widget over an old one, the background colors might mix if not handled correctly. The `Clear` widget resets the area to default (usually transparent/black) to ensure a clean canvas for popups.
11
+
12
+ ## Features Demonstrated
13
+
14
+ - **The `Clear` Widget**: Printing spaces over an area to "erase" what was underneath.
15
+ - **Centering**: Using `Layout` constraints to perfectly center a block on screen.
16
+ - **Style Bleed**: showing what happens when you *don't* use `Clear` (background colors leak through).
17
+
18
+ ## Hotkeys
19
+
20
+ - **Space**: Toggle Clear Widget (Observe the red background effect when disabled)
21
+ - **q**: Quit
22
+
23
+ ## Usage
24
+
25
+ ```bash
26
+ ruby examples/widget_popup_demo/app.rb
27
+ ```
28
+
29
+ ## Learning Outcomes
30
+
31
+ Use this example if you need to...
32
+ - Create a modal dialog (Confirm, Alert, Form).
33
+ - Implement a dropdown menu that overlays other content.
34
+ - Fix visual artifacts where old text shows through new widgets.
35
+
36
+ ![Demo](/doc/images/widget_popup_demo.png)
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-License-Identifier: AGPL-3.0-or-later
5
+
6
+ $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
+ require "ratatui_ruby"
8
+
9
+ # Popup Demo Example
10
+ # Demonstrates the Clear widget for creating opaque popups.
11
+
12
+ class WidgetPopupDemo
13
+ def initialize
14
+ @clear_enabled = false
15
+ end
16
+
17
+ def run
18
+ RatatuiRuby.run do |tui|
19
+ loop do
20
+ tui.draw do |frame|
21
+ render(tui, frame)
22
+ end
23
+ break if handle_input(tui) == :quit
24
+ sleep 0.05
25
+ end
26
+ end
27
+ end
28
+
29
+ private def render(tui, frame)
30
+ area = frame.area
31
+
32
+ # 1. Background: Loud Red Background
33
+ # This demonstrates "Style Bleed" where the background color persists
34
+ # unless explicitly cleared or overwritten.
35
+ background = tui.paragraph(
36
+ text: "BACKGROUND RED " * 100,
37
+ style: tui.style(bg: :red, fg: :white),
38
+ wrap: true
39
+ )
40
+ frame.render_widget(background, area)
41
+
42
+ # 2. Popup Area Calculation
43
+ # Center the popup vertically and horizontally
44
+ vertical_layout = tui.layout_split(
45
+ area,
46
+ direction: :vertical,
47
+ constraints: [
48
+ tui.constraint_percentage(25),
49
+ tui.constraint_percentage(50), # 50% height
50
+ tui.constraint_percentage(25),
51
+ ]
52
+ )
53
+ popup_area_vertical = vertical_layout[1]
54
+
55
+ horizontal_layout = tui.layout_split(
56
+ popup_area_vertical,
57
+ direction: :horizontal,
58
+ constraints: [
59
+ tui.constraint_percentage(20),
60
+ tui.constraint_percentage(60), # 60% width
61
+ tui.constraint_percentage(20),
62
+ ]
63
+ )
64
+ popup_area = horizontal_layout[1]
65
+
66
+ # 3. Popup Content
67
+ # Without Clear, this will "inherit" the red background from underneath.
68
+ popup_text = if @clear_enabled
69
+ "✓ Clear is ENABLED\n\nResets background to default\n(Usually Black/Transparent)\n\nPress Space to toggle"
70
+ else
71
+ "✗ Clear is DISABLED\n\nStyle Bleed: Popup is RED!\n(Inherits background style)\n\nPress Space to toggle"
72
+ end
73
+
74
+ popup_content = tui.paragraph(
75
+ text: popup_text,
76
+ alignment: :center,
77
+ block: tui.block(
78
+ title: "Popup Demo (q to quit, space to toggle)",
79
+ borders: [:all]
80
+ )
81
+ )
82
+
83
+ # 4. Render Popup
84
+ if @clear_enabled
85
+ # With Clear: Resets the style in the popup area before rendering content
86
+ frame.render_widget(tui.clear, popup_area)
87
+ end
88
+
89
+ frame.render_widget(popup_content, popup_area)
90
+ end
91
+
92
+ private def handle_input(tui)
93
+ case tui.poll_event
94
+ in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
95
+ :quit
96
+ in type: :key, code: " "
97
+ @clear_enabled = !@clear_enabled
98
+ else
99
+ nil
100
+ end
101
+ end
102
+ end
103
+
104
+ WidgetPopupDemo.new.run if __FILE__ == $0
@@ -0,0 +1,34 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Ratatui Logo Example
7
+
8
+ Demonstrates branding with the official logo widget.
9
+
10
+ A polished application often needs an "About" screen or a splash screen. This widget provides the standardized project branding.
11
+
12
+ ## Features Demonstrated
13
+
14
+ - **RatatuiLogo Widget**: Renders the Ratatui ASCII art logo.
15
+ - **Centering**: Techniques for centering fixed-size content in a fluid layout.
16
+
17
+ ## Hotkeys
18
+
19
+ - **q**: Quit
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ ruby examples/widget_ratatui_logo_demo/app.rb
25
+ ```
26
+
27
+ ## Learning Outcomes
28
+
29
+ Use this example if you need to...
30
+ - Create a splash screen.
31
+ - Add an "About" modal to your application.
32
+ - See how to center a widget both vertically and horizontally.
33
+
34
+ ![Demo](/doc/images/widget_ratatui_logo_demo.png)
@@ -0,0 +1,103 @@
1
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ #
3
+ # SPDX-License-Identifier: AGPL-3.0-or-later
4
+
5
+ # frozen_string_literal: true
6
+
7
+ $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
8
+ require "ratatui_ruby"
9
+
10
+ # Demonstrates branding visualization with the official logo.
11
+ #
12
+ # Branding is important for identity. Users need to recognize the tools they use.
13
+ #
14
+ # This demo showcases the <tt>RatatuiLogo</tt> widget. It renders the logo in a centered layout.
15
+ #
16
+ # Use it to understand how to incorporate the project's visual identity into your terminal application.
17
+ #
18
+ # === Example
19
+ #
20
+ # Run the demo from the terminal:
21
+ #
22
+ # ruby examples/widget_ratatui_logo_demo/app.rb
23
+ #
24
+ # rdoc-image:/doc/images/widget_ratatui_logo_demo.png
25
+ class WidgetRatatuiLogoDemo
26
+ def run
27
+ RatatuiRuby.run do |tui|
28
+ loop do
29
+ render(tui)
30
+ break if handle_input(tui) == :quit
31
+ end
32
+ end
33
+ end
34
+
35
+ private def render(tui)
36
+ tui.draw do |frame|
37
+ # Layout
38
+ layout = tui.layout_split(
39
+ frame.area,
40
+ direction: :vertical,
41
+ constraints: [
42
+ tui.constraint_fill(1), # Fill remaining space
43
+ tui.constraint_length(3),
44
+ ]
45
+ )
46
+
47
+ # Main Area
48
+ main_area = layout[0]
49
+
50
+ # Center the logo using nested Layouts
51
+ # Logo is roughly 47x8
52
+ # Vertical Center
53
+ v_center_layout = tui.layout_split(
54
+ main_area,
55
+ direction: :vertical,
56
+ flex: :center,
57
+ constraints: [tui.constraint_length(10)] # Height + margin
58
+ )
59
+
60
+ # Horizontal Center
61
+ h_center_layout = tui.layout_split(
62
+ v_center_layout[0],
63
+ direction: :horizontal,
64
+ flex: :center,
65
+ constraints: [tui.constraint_length(50)] # Width + margin
66
+ )
67
+
68
+ # Main content: The Logo
69
+ logo = RatatuiRuby::RatatuiLogo.new
70
+ frame.render_widget(logo, h_center_layout[0])
71
+
72
+ # Control Panel
73
+ control_area = layout[1]
74
+
75
+ control_text = tui.text_line(spans: [
76
+ tui.text_span(content: "q", style: tui.style(modifiers: [:bold, :underlined])),
77
+ tui.text_span(content: ": Quit"),
78
+ ])
79
+
80
+ control_panel = tui.paragraph(
81
+ text: [control_text],
82
+ block: tui.block(
83
+ title: "Controls",
84
+ borders: [:top],
85
+ style: tui.style(fg: :dark_gray)
86
+ )
87
+ )
88
+
89
+ frame.render_widget(control_panel, control_area)
90
+ end
91
+ end
92
+
93
+ private def handle_input(tui)
94
+ case tui.poll_event
95
+ in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
96
+ :quit
97
+ else
98
+ nil
99
+ end
100
+ end
101
+ end
102
+
103
+ WidgetRatatuiLogoDemo.new.run if __FILE__ == $0
@@ -0,0 +1,34 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Ratatui Mascot Example
7
+
8
+ Demonstrates the project mascot widget for adding personality.
9
+
10
+ Interfaces can feel clinical. A friendly mascot adds charm and brand identity to your terminal application.
11
+
12
+ ## Features Demonstrated
13
+
14
+ - **RatatuiMascot Widget**: Renders the ASCII art mascot.
15
+ - **Block Integration**: Wrapping the mascot in a bordered block title.
16
+
17
+ ## Hotkeys
18
+
19
+ - **b**: Toggle Block Border (`block`)
20
+ - **q**: Quit
21
+
22
+ ## Usage
23
+
24
+ ```bash
25
+ ruby examples/widget_ratatui_mascot_demo/app.rb
26
+ ```
27
+
28
+ ## Learning Outcomes
29
+
30
+ Use this example if you need to...
31
+ - Add visual flair to your UI.
32
+ - Create a friendly empty state or success screen.
33
+
34
+ ![Demo](/doc/images/widget_ratatui_mascot_demo.png)