ratatui_ruby 0.8.0 → 0.9.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 (352) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +2 -2
  3. data/.builds/ruby-3.3.yml +2 -2
  4. data/.builds/ruby-3.4.yml +2 -2
  5. data/.builds/ruby-4.0.0.yml +2 -2
  6. data/.pre-commit-config.yaml +1 -1
  7. data/AGENTS.md +3 -3
  8. data/CHANGELOG.md +53 -1
  9. data/LICENSES/LGPL-3.0-or-later.txt +304 -0
  10. data/LICENSES/MIT-0.txt +16 -0
  11. data/README.md +33 -5
  12. data/Rakefile +1 -1
  13. data/doc/concepts/application_architecture.md +44 -3
  14. data/doc/concepts/application_testing.md +43 -1
  15. data/doc/concepts/async.md +32 -2
  16. data/doc/concepts/custom_widgets.md +247 -0
  17. data/doc/concepts/event_handling.md +32 -3
  18. data/doc/concepts/interactive_design.md +32 -2
  19. data/doc/contributors/auditing/parity.md +7 -1
  20. data/doc/contributors/design/ruby_frontend.md +85 -1
  21. data/doc/contributors/design/rust_backend.md +67 -1
  22. data/doc/contributors/developing_examples.md +56 -2
  23. data/doc/contributors/documentation_style.md +20 -3
  24. data/doc/contributors/future_work.md +169 -0
  25. data/doc/contributors/index.md +1 -1
  26. data/doc/contributors/v1.0.0_blockers.md +15 -175
  27. data/doc/getting_started/quickstart.md +22 -4
  28. data/doc/getting_started/why.md +1 -1
  29. data/doc/index.md +2 -1
  30. data/doc/troubleshooting/debugging.md +32 -2
  31. data/doc/troubleshooting/terminal_limitations.md +8 -2
  32. data/doc/troubleshooting/tui_output.md +42 -0
  33. data/examples/app_all_events/README.md +14 -2
  34. data/examples/app_all_events/app.rb +1 -1
  35. data/examples/app_all_events/model/app_model.rb +1 -1
  36. data/examples/app_all_events/model/event_color_cycle.rb +1 -1
  37. data/examples/app_all_events/model/event_entry.rb +1 -1
  38. data/examples/app_all_events/model/msg.rb +1 -1
  39. data/examples/app_all_events/model/timestamp.rb +1 -1
  40. data/examples/app_all_events/update.rb +1 -1
  41. data/examples/app_all_events/view/app_view.rb +1 -1
  42. data/examples/app_all_events/view/controls_view.rb +1 -1
  43. data/examples/app_all_events/view/counts_view.rb +1 -1
  44. data/examples/app_all_events/view/live_view.rb +1 -1
  45. data/examples/app_all_events/view/log_view.rb +1 -1
  46. data/examples/app_all_events/view.rb +1 -1
  47. data/examples/app_color_picker/README.md +20 -2
  48. data/examples/app_color_picker/app.rb +1 -1
  49. data/examples/app_color_picker/clipboard.rb +1 -1
  50. data/examples/app_color_picker/color.rb +1 -1
  51. data/examples/app_color_picker/controls.rb +1 -1
  52. data/examples/app_color_picker/copy_dialog.rb +1 -1
  53. data/examples/app_color_picker/export_pane.rb +1 -1
  54. data/examples/app_color_picker/harmony.rb +1 -1
  55. data/examples/app_color_picker/input.rb +1 -1
  56. data/examples/app_color_picker/main_container.rb +1 -1
  57. data/examples/app_color_picker/palette.rb +1 -1
  58. data/examples/app_login_form/README.md +8 -2
  59. data/examples/app_login_form/app.rb +1 -1
  60. data/examples/app_stateful_interaction/README.md +2 -2
  61. data/examples/app_stateful_interaction/app.rb +71 -17
  62. data/examples/timeout_demo.rb +1 -1
  63. data/examples/verify_quickstart_dsl/README.md +6 -0
  64. data/examples/verify_quickstart_dsl/app.rb +3 -3
  65. data/examples/verify_quickstart_layout/README.md +6 -0
  66. data/examples/verify_quickstart_layout/app.rb +3 -3
  67. data/examples/verify_quickstart_lifecycle/README.md +6 -0
  68. data/examples/verify_quickstart_lifecycle/app.rb +3 -3
  69. data/examples/verify_readme_usage/README.md +6 -0
  70. data/examples/verify_readme_usage/app.rb +3 -3
  71. data/examples/widget_barchart/README.md +6 -0
  72. data/examples/widget_barchart/app.rb +2 -2
  73. data/examples/widget_block/README.md +7 -1
  74. data/examples/widget_block/app.rb +2 -2
  75. data/examples/widget_box/README.md +6 -0
  76. data/examples/widget_box/app.rb +9 -6
  77. data/examples/widget_calendar/README.md +6 -0
  78. data/examples/widget_calendar/app.rb +2 -2
  79. data/examples/widget_canvas/README.md +4 -0
  80. data/examples/widget_canvas/app.rb +2 -2
  81. data/examples/widget_cell/README.md +6 -0
  82. data/examples/widget_cell/app.rb +2 -3
  83. data/examples/widget_center/README.md +4 -0
  84. data/examples/widget_center/app.rb +2 -2
  85. data/examples/widget_chart/README.md +6 -0
  86. data/examples/widget_chart/app.rb +2 -2
  87. data/examples/widget_gauge/README.md +6 -0
  88. data/examples/widget_gauge/app.rb +2 -2
  89. data/examples/widget_layout_split/README.md +6 -0
  90. data/examples/widget_layout_split/app.rb +3 -3
  91. data/examples/widget_line_gauge/README.md +6 -0
  92. data/examples/widget_line_gauge/app.rb +2 -2
  93. data/examples/widget_list/README.md +6 -0
  94. data/examples/widget_list/app.rb +2 -2
  95. data/examples/widget_map/README.md +8 -2
  96. data/examples/widget_map/app.rb +2 -2
  97. data/examples/widget_overlay/README.md +7 -1
  98. data/examples/widget_overlay/app.rb +2 -2
  99. data/examples/widget_popup/README.md +6 -0
  100. data/examples/widget_popup/app.rb +2 -2
  101. data/examples/widget_ratatui_logo/README.md +6 -0
  102. data/examples/widget_ratatui_logo/app.rb +2 -3
  103. data/examples/widget_ratatui_mascot/README.md +6 -0
  104. data/examples/widget_ratatui_mascot/app.rb +2 -2
  105. data/examples/widget_rect/README.md +12 -0
  106. data/examples/widget_rect/app.rb +40 -26
  107. data/examples/widget_render/README.md +6 -0
  108. data/examples/widget_render/app.rb +2 -2
  109. data/examples/widget_render/app.rbs +41 -0
  110. data/examples/widget_rich_text/README.md +6 -0
  111. data/examples/widget_rich_text/app.rb +2 -2
  112. data/examples/widget_scroll_text/README.md +6 -0
  113. data/examples/widget_scroll_text/app.rb +2 -2
  114. data/examples/widget_scrollbar/README.md +6 -0
  115. data/examples/widget_scrollbar/app.rb +2 -2
  116. data/examples/widget_sparkline/README.md +6 -0
  117. data/examples/widget_sparkline/app.rb +2 -2
  118. data/examples/widget_style_colors/README.md +6 -0
  119. data/examples/widget_style_colors/app.rb +2 -2
  120. data/examples/widget_table/README.md +8 -2
  121. data/examples/widget_table/app.rb +2 -2
  122. data/examples/widget_tabs/README.md +6 -0
  123. data/examples/widget_tabs/app.rb +2 -2
  124. data/examples/widget_text_width/README.md +6 -0
  125. data/examples/widget_text_width/app.rb +4 -4
  126. data/ext/ratatui_ruby/Cargo.lock +1 -1
  127. data/ext/ratatui_ruby/Cargo.toml +1 -1
  128. data/ext/ratatui_ruby/extconf.rb +2 -2
  129. data/ext/ratatui_ruby/src/rendering.rs +1 -1
  130. data/ext/ratatui_ruby/src/style.rs +0 -8
  131. data/ext/ratatui_ruby/src/widgets/chart.rs +0 -118
  132. data/ext/ratatui_ruby/src/widgets/list_state.rs +36 -0
  133. data/lib/ratatui_ruby/buffer/cell.rb +34 -2
  134. data/lib/ratatui_ruby/buffer.rb +2 -2
  135. data/lib/ratatui_ruby/cell.rb +34 -2
  136. data/lib/ratatui_ruby/event/focus_gained.rb +26 -2
  137. data/lib/ratatui_ruby/event/focus_lost.rb +26 -2
  138. data/lib/ratatui_ruby/event/key/character.rb +18 -2
  139. data/lib/ratatui_ruby/event/key/media.rb +2 -2
  140. data/lib/ratatui_ruby/event/key/modifier.rb +10 -2
  141. data/lib/ratatui_ruby/event/key/navigation.rb +2 -2
  142. data/lib/ratatui_ruby/event/key/system.rb +2 -2
  143. data/lib/ratatui_ruby/event/key.rb +114 -2
  144. data/lib/ratatui_ruby/event/mouse.rb +42 -2
  145. data/lib/ratatui_ruby/event/none.rb +10 -2
  146. data/lib/ratatui_ruby/event/paste.rb +34 -2
  147. data/lib/ratatui_ruby/event/resize.rb +34 -2
  148. data/lib/ratatui_ruby/event.rb +26 -2
  149. data/lib/ratatui_ruby/frame.rb +74 -2
  150. data/lib/ratatui_ruby/layout/constraint.rb +58 -2
  151. data/lib/ratatui_ruby/layout/layout.rb +47 -2
  152. data/lib/ratatui_ruby/layout/rect.rb +403 -2
  153. data/lib/ratatui_ruby/layout.rb +2 -2
  154. data/lib/ratatui_ruby/list_state.rb +113 -2
  155. data/lib/ratatui_ruby/output_guard.rb +26 -3
  156. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -2
  157. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +2 -2
  158. data/lib/ratatui_ruby/schema/bar_chart.rb +50 -2
  159. data/lib/ratatui_ruby/schema/block.rb +21 -15
  160. data/lib/ratatui_ruby/schema/calendar.rb +2 -2
  161. data/lib/ratatui_ruby/schema/canvas.rb +10 -2
  162. data/lib/ratatui_ruby/schema/center.rb +10 -2
  163. data/lib/ratatui_ruby/schema/chart.rb +2 -28
  164. data/lib/ratatui_ruby/schema/clear.rb +10 -2
  165. data/lib/ratatui_ruby/schema/constraint.rb +58 -2
  166. data/lib/ratatui_ruby/schema/cursor.rb +10 -2
  167. data/lib/ratatui_ruby/schema/draw.rb +10 -2
  168. data/lib/ratatui_ruby/schema/gauge.rb +2 -2
  169. data/lib/ratatui_ruby/schema/layout.rb +18 -2
  170. data/lib/ratatui_ruby/schema/line_gauge.rb +2 -2
  171. data/lib/ratatui_ruby/schema/list.rb +10 -2
  172. data/lib/ratatui_ruby/schema/list_item.rb +10 -2
  173. data/lib/ratatui_ruby/schema/overlay.rb +10 -2
  174. data/lib/ratatui_ruby/schema/paragraph.rb +10 -2
  175. data/lib/ratatui_ruby/schema/ratatui_logo.rb +2 -2
  176. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +2 -2
  177. data/lib/ratatui_ruby/schema/rect.rb +58 -2
  178. data/lib/ratatui_ruby/schema/row.rb +10 -2
  179. data/lib/ratatui_ruby/schema/scrollbar.rb +2 -2
  180. data/lib/ratatui_ruby/schema/shape/label.rb +10 -2
  181. data/lib/ratatui_ruby/schema/sparkline.rb +10 -2
  182. data/lib/ratatui_ruby/schema/style.rb +18 -2
  183. data/lib/ratatui_ruby/schema/table.rb +2 -2
  184. data/lib/ratatui_ruby/schema/tabs.rb +2 -2
  185. data/lib/ratatui_ruby/schema/text.rb +34 -2
  186. data/lib/ratatui_ruby/scrollbar_state.rb +10 -2
  187. data/lib/ratatui_ruby/style/style.rb +18 -2
  188. data/lib/ratatui_ruby/style.rb +2 -2
  189. data/lib/ratatui_ruby/table_state.rb +10 -2
  190. data/lib/ratatui_ruby/terminal_lifecycle.rb +18 -3
  191. data/lib/ratatui_ruby/test_helper/event_injection.rb +34 -2
  192. data/lib/ratatui_ruby/test_helper/snapshot.rb +74 -9
  193. data/lib/ratatui_ruby/test_helper/style_assertions.rb +98 -2
  194. data/lib/ratatui_ruby/test_helper/terminal.rb +50 -2
  195. data/lib/ratatui_ruby/test_helper/test_doubles.rb +18 -2
  196. data/lib/ratatui_ruby/test_helper.rb +10 -2
  197. data/lib/ratatui_ruby/tui/buffer_factories.rb +2 -2
  198. data/lib/ratatui_ruby/tui/canvas_factories.rb +2 -2
  199. data/lib/ratatui_ruby/tui/core.rb +2 -2
  200. data/lib/ratatui_ruby/tui/layout_factories.rb +32 -2
  201. data/lib/ratatui_ruby/tui/state_factories.rb +2 -2
  202. data/lib/ratatui_ruby/tui/style_factories.rb +2 -2
  203. data/lib/ratatui_ruby/tui/text_factories.rb +2 -2
  204. data/lib/ratatui_ruby/tui/widget_factories.rb +2 -2
  205. data/lib/ratatui_ruby/tui.rb +11 -3
  206. data/lib/ratatui_ruby/version.rb +3 -3
  207. data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -2
  208. data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -2
  209. data/lib/ratatui_ruby/widgets/bar_chart.rb +58 -2
  210. data/lib/ratatui_ruby/widgets/block.rb +37 -15
  211. data/lib/ratatui_ruby/widgets/calendar.rb +2 -2
  212. data/lib/ratatui_ruby/widgets/canvas.rb +10 -2
  213. data/lib/ratatui_ruby/widgets/cell.rb +10 -2
  214. data/lib/ratatui_ruby/widgets/center.rb +10 -2
  215. data/lib/ratatui_ruby/widgets/chart.rb +2 -28
  216. data/lib/ratatui_ruby/widgets/clear.rb +10 -2
  217. data/lib/ratatui_ruby/widgets/cursor.rb +10 -2
  218. data/lib/ratatui_ruby/widgets/gauge.rb +16 -2
  219. data/lib/ratatui_ruby/widgets/line_gauge.rb +16 -2
  220. data/lib/ratatui_ruby/widgets/list.rb +41 -2
  221. data/lib/ratatui_ruby/widgets/list_item.rb +10 -2
  222. data/lib/ratatui_ruby/widgets/overlay.rb +10 -2
  223. data/lib/ratatui_ruby/widgets/paragraph.rb +10 -2
  224. data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -2
  225. data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -2
  226. data/lib/ratatui_ruby/widgets/row.rb +10 -2
  227. data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -2
  228. data/lib/ratatui_ruby/widgets/shape/label.rb +10 -2
  229. data/lib/ratatui_ruby/widgets/sparkline.rb +10 -2
  230. data/lib/ratatui_ruby/widgets/table.rb +62 -2
  231. data/lib/ratatui_ruby/widgets/tabs.rb +2 -2
  232. data/lib/ratatui_ruby/widgets.rb +2 -2
  233. data/lib/ratatui_ruby.rb +90 -2
  234. data/sig/examples/app_all_events/view.rbs +7 -1
  235. data/sig/examples/app_all_events/view_state.rbs +7 -1
  236. data/sig/examples/app_color_picker/app.rbs +5 -0
  237. data/sig/examples/app_stateful_interaction/app.rbs +7 -1
  238. data/sig/examples/verify_quickstart_dsl/app.rbs +7 -1
  239. data/sig/examples/verify_quickstart_lifecycle/app.rbs +7 -1
  240. data/sig/examples/verify_readme_usage/app.rbs +7 -1
  241. data/sig/examples/widget_block_demo/app.rbs +6 -0
  242. data/sig/examples/widget_box_demo/app.rbs +7 -1
  243. data/sig/examples/widget_calendar_demo/app.rbs +7 -1
  244. data/sig/examples/widget_cell_demo/app.rbs +7 -1
  245. data/sig/examples/widget_chart_demo/app.rbs +7 -1
  246. data/sig/examples/widget_gauge_demo/app.rbs +7 -1
  247. data/sig/examples/widget_layout_split/app.rbs +7 -1
  248. data/sig/examples/widget_line_gauge_demo/app.rbs +7 -1
  249. data/sig/examples/widget_list_demo/app.rbs +5 -0
  250. data/sig/examples/widget_map_demo/app.rbs +7 -1
  251. data/sig/examples/widget_popup_demo/app.rbs +7 -1
  252. data/sig/examples/widget_ratatui_logo_demo/app.rbs +7 -1
  253. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +7 -1
  254. data/sig/examples/widget_rect/app.rbs +7 -1
  255. data/sig/examples/widget_render/app.rbs +7 -1
  256. data/sig/examples/widget_rich_text/app.rbs +7 -1
  257. data/sig/examples/widget_scroll_text/app.rbs +7 -1
  258. data/sig/examples/widget_scrollbar_demo/app.rbs +7 -1
  259. data/sig/examples/widget_sparkline_demo/app.rbs +7 -1
  260. data/sig/examples/widget_style_colors/app.rbs +7 -1
  261. data/sig/examples/widget_table_demo/app.rbs +7 -1
  262. data/sig/examples/widget_text_width/app.rbs +7 -1
  263. data/sig/ratatui_ruby/event.rbs +7 -1
  264. data/sig/ratatui_ruby/frame.rbs +15 -3
  265. data/sig/ratatui_ruby/list_state.rbs +11 -1
  266. data/sig/ratatui_ruby/ratatui_ruby.rbs +8 -2
  267. data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +7 -1
  268. data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +6 -0
  269. data/sig/ratatui_ruby/schema/bar_chart.rbs +6 -0
  270. data/sig/ratatui_ruby/schema/block.rbs +7 -1
  271. data/sig/ratatui_ruby/schema/calendar.rbs +6 -0
  272. data/sig/ratatui_ruby/schema/canvas.rbs +6 -0
  273. data/sig/ratatui_ruby/schema/center.rbs +6 -0
  274. data/sig/ratatui_ruby/schema/chart.rbs +6 -9
  275. data/sig/ratatui_ruby/schema/constraint.rbs +6 -0
  276. data/sig/ratatui_ruby/schema/cursor.rbs +6 -0
  277. data/sig/ratatui_ruby/schema/draw.rbs +6 -0
  278. data/sig/ratatui_ruby/schema/gauge.rbs +9 -1
  279. data/sig/ratatui_ruby/schema/layout.rbs +6 -0
  280. data/sig/ratatui_ruby/schema/line_gauge.rbs +9 -1
  281. data/sig/ratatui_ruby/schema/list.rbs +9 -1
  282. data/sig/ratatui_ruby/schema/list_item.rbs +7 -1
  283. data/sig/ratatui_ruby/schema/overlay.rbs +6 -0
  284. data/sig/ratatui_ruby/schema/paragraph.rbs +6 -0
  285. data/sig/ratatui_ruby/schema/ratatui_logo.rbs +6 -0
  286. data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +5 -0
  287. data/sig/ratatui_ruby/schema/rect.rbs +30 -0
  288. data/sig/ratatui_ruby/schema/row.rbs +7 -1
  289. data/sig/ratatui_ruby/schema/scrollbar.rbs +6 -0
  290. data/sig/ratatui_ruby/schema/sparkline.rbs +6 -0
  291. data/sig/ratatui_ruby/schema/style.rbs +7 -1
  292. data/sig/ratatui_ruby/schema/table.rbs +11 -1
  293. data/sig/ratatui_ruby/schema/tabs.rbs +6 -0
  294. data/sig/ratatui_ruby/schema/text.rbs +7 -1
  295. data/sig/ratatui_ruby/scrollbar_state.rbs +7 -1
  296. data/sig/ratatui_ruby/session.rbs +7 -1
  297. data/sig/ratatui_ruby/table_state.rbs +7 -1
  298. data/sig/ratatui_ruby/test_helper/event_injection.rbs +7 -1
  299. data/sig/ratatui_ruby/test_helper/snapshot.rbs +7 -1
  300. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +7 -1
  301. data/sig/ratatui_ruby/test_helper/terminal.rbs +7 -1
  302. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -1
  303. data/sig/ratatui_ruby/test_helper.rbs +7 -1
  304. data/sig/ratatui_ruby/tui/buffer_factories.rbs +7 -1
  305. data/sig/ratatui_ruby/tui/canvas_factories.rbs +7 -1
  306. data/sig/ratatui_ruby/tui/core.rbs +7 -1
  307. data/sig/ratatui_ruby/tui/layout_factories.rbs +7 -1
  308. data/sig/ratatui_ruby/tui/state_factories.rbs +7 -1
  309. data/sig/ratatui_ruby/tui/style_factories.rbs +7 -1
  310. data/sig/ratatui_ruby/tui/text_factories.rbs +7 -1
  311. data/sig/ratatui_ruby/tui/widget_factories.rbs +7 -1
  312. data/sig/ratatui_ruby/tui.rbs +7 -1
  313. data/sig/ratatui_ruby/version.rbs +6 -0
  314. data/tasks/autodoc/examples.rb +1 -1
  315. data/tasks/autodoc/member.rb +1 -1
  316. data/tasks/autodoc/name.rb +1 -1
  317. data/tasks/bump/cargo_lockfile.rb +1 -1
  318. data/tasks/bump/changelog.rb +1 -1
  319. data/tasks/bump/header.rb +1 -1
  320. data/tasks/bump/history.rb +1 -1
  321. data/tasks/bump/links.rb +1 -1
  322. data/tasks/bump/manifest.rb +1 -1
  323. data/tasks/bump/ruby_gem.rb +1 -1
  324. data/tasks/bump/sem_ver.rb +1 -1
  325. data/tasks/bump/unreleased_section.rb +1 -1
  326. data/tasks/license/headers_md.rb +223 -0
  327. data/tasks/license/headers_rb.rb +210 -0
  328. data/tasks/license/license_utils.rb +130 -0
  329. data/tasks/license/snippets_md.rb +315 -0
  330. data/tasks/license/snippets_rdoc.rb +150 -0
  331. data/tasks/license.rake +91 -0
  332. data/tasks/rdoc_config.rb +1 -1
  333. data/tasks/resources/build.yml.erb +13 -7
  334. data/tasks/sourcehut.rake +3 -1
  335. data/tasks/terminal_preview/app_screenshot.rb +1 -1
  336. data/tasks/terminal_preview/crash_report.rb +1 -1
  337. data/tasks/terminal_preview/example_app.rb +1 -1
  338. data/tasks/terminal_preview/launcher_script.rb +1 -1
  339. data/tasks/terminal_preview/preview_collection.rb +1 -1
  340. data/tasks/terminal_preview/preview_timing.rb +1 -1
  341. data/tasks/terminal_preview/safety_confirmation.rb +1 -1
  342. data/tasks/terminal_preview/saved_screenshot.rb +1 -1
  343. data/tasks/terminal_preview/system_appearance.rb +1 -1
  344. data/tasks/terminal_preview/terminal_window.rb +1 -1
  345. data/tasks/terminal_preview/window_id.rb +1 -1
  346. data/tasks/website/index_page.rb +1 -1
  347. data/tasks/website/version.rb +1 -1
  348. data/tasks/website/version_menu.rb +1 -1
  349. data/tasks/website/versioned_documentation.rb +1 -1
  350. data/tasks/website/website.rb +1 -1
  351. metadata +13 -3
  352. data/doc/migration/v0_7_0.md +0 -236
@@ -1,5 +1,5 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
3
  SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
  # Quickstart
@@ -17,6 +17,11 @@ See [Installation in the README](../README.md#installation) for setup instructio
17
17
 
18
18
  Here is a "Hello World" application that demonstrates the core lifecycle of a **ratatui_ruby** app.
19
19
 
20
+ <!-- SPDX-SnippetBegin -->
21
+ <!--
22
+ SPDX-FileCopyrightText: 2026 Kerrick Long
23
+ SPDX-License-Identifier: MIT-0
24
+ -->
20
25
  <!-- SYNC:START:examples/verify_quickstart_lifecycle/app.rb:main -->
21
26
  ```ruby
22
27
  # 1. Initialize the terminal
@@ -34,7 +39,7 @@ begin
34
39
  title: "My Ruby TUI App",
35
40
  title_alignment: :center,
36
41
  borders: [:all],
37
- border_color: "cyan",
42
+ border_style: { fg: "cyan" },
38
43
  style: { fg: "white" }
39
44
  )
40
45
  )
@@ -64,6 +69,7 @@ ensure
64
69
  end
65
70
  ```
66
71
  <!-- SYNC:END -->
72
+ <!-- SPDX-SnippetEnd -->
67
73
 
68
74
  [![quickstart_lifecycle](../images/verify_quickstart_lifecycle.png)](../../examples/verify_quickstart_lifecycle/README.md)
69
75
 
@@ -80,6 +86,11 @@ end
80
86
 
81
87
  You can simplify your code by using `RatatuiRuby.run`. This method handles the terminal lifecycle for you, yielding a `TUI` object with factory methods for widgets.
82
88
 
89
+ <!-- SPDX-SnippetBegin -->
90
+ <!--
91
+ SPDX-FileCopyrightText: 2026 Kerrick Long
92
+ SPDX-License-Identifier: MIT-0
93
+ -->
83
94
  <!-- SYNC:START:examples/verify_quickstart_dsl/app.rb:main -->
84
95
  ```ruby
85
96
  # 1. Initialize the terminal, start the run loop, and ensure the terminal is restored.
@@ -93,7 +104,7 @@ RatatuiRuby.run do |tui|
93
104
  title: "My Ruby TUI App",
94
105
  title_alignment: :center,
95
106
  borders: [:all],
96
- border_color: "cyan",
107
+ border_style: { fg: "cyan" },
97
108
  style: { fg: "white" }
98
109
  )
99
110
  )
@@ -114,6 +125,7 @@ RatatuiRuby.run do |tui|
114
125
  end
115
126
  ```
116
127
  <!-- SYNC:END -->
128
+ <!-- SPDX-SnippetEnd -->
117
129
 
118
130
  #### How it works
119
131
 
@@ -128,6 +140,11 @@ For a deeper dive into the available application architectures (Manual vs Manage
128
140
 
129
141
  Real-world applications often need to split the screen into multiple areas. `RatatuiRuby::Layout` lets you do this easily.
130
142
 
143
+ <!-- SPDX-SnippetBegin -->
144
+ <!--
145
+ SPDX-FileCopyrightText: 2026 Kerrick Long
146
+ SPDX-License-Identifier: MIT-0
147
+ -->
131
148
  <!-- SYNC:START:examples/verify_quickstart_layout/app.rb:main -->
132
149
  ```ruby
133
150
  loop do
@@ -147,7 +164,7 @@ loop do
147
164
  tui.paragraph(
148
165
  text: "Hello, Ratatui!",
149
166
  alignment: :center,
150
- block: tui.block(title: "Content", borders: [:all], border_color: "cyan")
167
+ block: tui.block(title: "Content", borders: [:all], border_style: { fg: "cyan" })
151
168
  ),
152
169
  top
153
170
  )
@@ -184,6 +201,7 @@ loop do
184
201
  end
185
202
  ```
186
203
  <!-- SYNC:END -->
204
+ <!-- SPDX-SnippetEnd -->
187
205
 
188
206
  #### How it works
189
207
 
@@ -1,5 +1,5 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
3
  SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
  # Why RatatuiRuby?
data/doc/index.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
3
  SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
  # Start Here
@@ -20,6 +20,7 @@
20
20
  - [Event Handling](./concepts/event_handling.md): Keyboard, mouse, and terminal events
21
21
  - [Interactive Design](./concepts/interactive_design.md): Cached layout pattern for hit testing
22
22
  - [Testing Your Application](./concepts/application_testing.md): Snapshot testing and style assertions
23
+ - [Custom Widgets](./concepts/custom_widgets.md): Build anything with the Draw API
23
24
  - [Async Operations](./concepts/async.md): Background tasks and non-blocking I/O
24
25
 
25
26
  ### Troubleshooting
@@ -1,6 +1,6 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: AGPL-3.0-or-later
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
 
6
6
  # Debugging TUI Applications
@@ -15,6 +15,11 @@ Write debug output to files. Tail them in a separate terminal.
15
15
 
16
16
  Create timestamped log files to avoid overwrites:
17
17
 
18
+ <!-- SPDX-SnippetBegin -->
19
+ <!--
20
+ SPDX-FileCopyrightText: 2026 Kerrick Long
21
+ SPDX-License-Identifier: MIT-0
22
+ -->
18
23
  ```ruby
19
24
  FileUtils.mkdir_p(File.join(Dir.tmpdir, "my_debug"))
20
25
  timestamp = Time.now.strftime('%Y%m%d_%H%M%S_%N')
@@ -23,15 +28,27 @@ File.write(
23
28
  "variable=#{value.inspect}\n"
24
29
  )
25
30
  ```
31
+ <!-- SPDX-SnippetEnd -->
26
32
 
27
33
  Or append to a single file:
28
34
 
35
+ <!-- SPDX-SnippetBegin -->
36
+ <!--
37
+ SPDX-FileCopyrightText: 2026 Kerrick Long
38
+ SPDX-License-Identifier: MIT-0
39
+ -->
29
40
  ```ruby
30
41
  File.write("/tmp/debug.log", "#{Time.now}: #{message}\n", mode: "a")
31
42
  ```
43
+ <!-- SPDX-SnippetEnd -->
32
44
 
33
45
  Tail the logs in a separate terminal:
34
46
 
47
+ <!-- SPDX-SnippetBegin -->
48
+ <!--
49
+ SPDX-FileCopyrightText: 2026 Kerrick Long
50
+ SPDX-License-Identifier: MIT-0
51
+ -->
35
52
  ```bash
36
53
  # Single file
37
54
  tail -f /tmp/debug.log
@@ -39,6 +56,7 @@ tail -f /tmp/debug.log
39
56
  # Directory of timestamped files
40
57
  watch -n 0.5 'ls -la /tmp/my_debug/ && cat /tmp/my_debug/*.log'
41
58
  ```
59
+ <!-- SPDX-SnippetEnd -->
42
60
 
43
61
  ## REPL Debugging with `__FILE__` Guards
44
62
 
@@ -46,17 +64,29 @@ Unit tests verify correctness. But during exploratory debugging, you want to pok
46
64
 
47
65
  Wrap your main execution in a guard:
48
66
 
67
+ <!-- SPDX-SnippetBegin -->
68
+ <!--
69
+ SPDX-FileCopyrightText: 2026 Kerrick Long
70
+ SPDX-License-Identifier: MIT-0
71
+ -->
49
72
  ```ruby
50
73
  if __FILE__ == $PROGRAM_NAME
51
74
  MyApp.new.run
52
75
  end
53
76
  ```
77
+ <!-- SPDX-SnippetEnd -->
54
78
 
55
79
  Now load the file and interact with classes directly:
56
80
 
81
+ <!-- SPDX-SnippetBegin -->
82
+ <!--
83
+ SPDX-FileCopyrightText: 2026 Kerrick Long
84
+ SPDX-License-Identifier: MIT-0
85
+ -->
57
86
  ```bash
58
87
  ruby -e 'load "./bin/my_tui"; obj = MyClass.new; sleep 1; puts obj.result'
59
88
  ```
89
+ <!-- SPDX-SnippetEnd -->
60
90
 
61
91
  This exercises domain logic without entering raw terminal mode. Use it for exploratory debugging. Write tests using the [TestHelper](application_testing.md) for regression coverage.
62
92
 
@@ -1,6 +1,6 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
 
6
6
  # Terminal Limitations
@@ -114,12 +114,18 @@ There's no way to catch SIGKILL. You can only mitigate the impact.
114
114
 
115
115
  **Script graceful shutdowns.** If you write deployment or process management scripts, prefer graceful signals with a timeout before SIGKILL:
116
116
 
117
+ <!-- SPDX-SnippetBegin -->
118
+ <!--
119
+ SPDX-FileCopyrightText: 2026 Kerrick Long
120
+ SPDX-License-Identifier: MIT-0
121
+ -->
117
122
  ```bash
118
123
  # Graceful first, force if needed
119
124
  kill -15 $PID
120
125
  sleep 2
121
126
  kill -0 $PID 2>/dev/null && kill -9 $PID
122
127
  ```
128
+ <!-- SPDX-SnippetEnd -->
123
129
 
124
130
  See [Application Architecture: Signal Handling](../concepts/application_architecture.md#signal-handling) for programmatic cleanup strategies.
125
131
 
@@ -28,6 +28,11 @@ In raw mode:
28
28
 
29
29
  If you're using a gem that might write to stdout/stderr, wrap its calls:
30
30
 
31
+ <!-- SPDX-SnippetBegin -->
32
+ <!--
33
+ SPDX-FileCopyrightText: 2026 Kerrick Long
34
+ SPDX-License-Identifier: MIT-0
35
+ -->
31
36
  ```ruby
32
37
  RatatuiRuby.run do |tui|
33
38
  RatatuiRuby.guard_io do
@@ -38,9 +43,15 @@ RatatuiRuby.run do |tui|
38
43
  # Object::STDERR.puts "debug: something" # Escape hatch (corrupts display!)
39
44
  end
40
45
  ```
46
+ <!-- SPDX-SnippetEnd -->
41
47
 
42
48
  ### Defer output until after the TUI exits
43
49
 
50
+ <!-- SPDX-SnippetBegin -->
51
+ <!--
52
+ SPDX-FileCopyrightText: 2026 Kerrick Long
53
+ SPDX-License-Identifier: MIT-0
54
+ -->
44
55
  ```ruby
45
56
  messages = []
46
57
 
@@ -54,11 +65,17 @@ end
54
65
  # Now safe to print
55
66
  messages.each { |msg| puts msg }
56
67
  ```
68
+ <!-- SPDX-SnippetEnd -->
57
69
 
58
70
  ### Use Logger to write to a file
59
71
 
60
72
  The `Logger` class from Ruby's standard library is the idiomatic solution:
61
73
 
74
+ <!-- SPDX-SnippetBegin -->
75
+ <!--
76
+ SPDX-FileCopyrightText: 2026 Kerrick Long
77
+ SPDX-License-Identifier: MIT-0
78
+ -->
62
79
  ```ruby
63
80
  require "logger"
64
81
  require "tmpdir"
@@ -73,9 +90,15 @@ RatatuiRuby.run do |tui|
73
90
  # ... TUI logic ...
74
91
  end
75
92
  ```
93
+ <!-- SPDX-SnippetEnd -->
76
94
 
77
95
  ### Display messages in the TUI itself
78
96
 
97
+ <!-- SPDX-SnippetBegin -->
98
+ <!--
99
+ SPDX-FileCopyrightText: 2026 Kerrick Long
100
+ SPDX-License-Identifier: MIT-0
101
+ -->
79
102
  ```ruby
80
103
  RatatuiRuby.run do |tui|
81
104
  @status_message = "Something happened"
@@ -89,6 +112,7 @@ RatatuiRuby.run do |tui|
89
112
  end
90
113
  end
91
114
  ```
115
+ <!-- SPDX-SnippetEnd -->
92
116
 
93
117
  ## Library Behavior
94
118
 
@@ -100,6 +124,11 @@ You don't need to do anything special for library warnings—they're handled aut
100
124
 
101
125
  If you need to write to stdout/stderr even when `guard_io` is active (e.g., for [pipeline integration](#headless-mode-batchpipelinecli) or IPC), use the original IO constants:
102
126
 
127
+ <!-- SPDX-SnippetBegin -->
128
+ <!--
129
+ SPDX-FileCopyrightText: 2026 Kerrick Long
130
+ SPDX-License-Identifier: MIT-0
131
+ -->
103
132
  ```ruby
104
133
  RatatuiRuby.guard_io do
105
134
  SomeChattyGem.do_something # This is swallowed
@@ -108,6 +137,7 @@ RatatuiRuby.guard_io do
108
137
  Object::STDOUT.puts "structured output for downstream tools"
109
138
  end
110
139
  ```
140
+ <!-- SPDX-SnippetEnd -->
111
141
 
112
142
  This works regardless of whether `guard_io` is active. During a TUI session, the display will be corrupted—but the output will reach its destination.
113
143
 
@@ -115,6 +145,11 @@ This works regardless of whether `guard_io` is active. During a TUI session, the
115
145
 
116
146
  If your app supports both TUI and non-TUI modes (e.g., `my_app --no-tui`), call `headless!` at startup to silence `guard_io` warnings:
117
147
 
148
+ <!-- SPDX-SnippetBegin -->
149
+ <!--
150
+ SPDX-FileCopyrightText: 2026 Kerrick Long
151
+ SPDX-License-Identifier: MIT-0
152
+ -->
118
153
  ```ruby
119
154
  if ARGV.include?("--no-tui")
120
155
  RatatuiRuby.headless!
@@ -126,6 +161,7 @@ else
126
161
  end
127
162
  end
128
163
  ```
164
+ <!-- SPDX-SnippetEnd -->
129
165
 
130
166
  When headless, `guard_io` becomes a no-op (output flows normally), and calling `run` or `init_terminal` raises an error.
131
167
 
@@ -133,6 +169,11 @@ When headless, `guard_io` becomes a no-op (output flows normally), and calling `
133
169
 
134
170
  Some apps need to temporarily leave TUI mode for user interaction—like lazygit does when opening an external editor for commit messages. Use `restore_terminal` and `init_terminal`:
135
171
 
172
+ <!-- SPDX-SnippetBegin -->
173
+ <!--
174
+ SPDX-FileCopyrightText: 2026 Kerrick Long
175
+ SPDX-License-Identifier: MIT-0
176
+ -->
136
177
  ```ruby
137
178
  RatatuiRuby.run do |tui|
138
179
  # ... TUI is active ...
@@ -151,5 +192,6 @@ RatatuiRuby.run do |tui|
151
192
  # ... TUI is active again ...
152
193
  end
153
194
  ```
195
+ <!-- SPDX-SnippetEnd -->
154
196
 
155
197
  This pattern lets you hand control back to the user or spawn external processes that need normal terminal access.
@@ -1,6 +1,6 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
 
6
6
  # App All Events Example
@@ -33,9 +33,15 @@ Semantic value objects that decouple raw terminal events from business logic:
33
33
  ### 3. Update (`update.rb`)
34
34
  A **pure function** that computes the next state:
35
35
 
36
+ <!-- SPDX-SnippetBegin -->
37
+ <!--
38
+ SPDX-FileCopyrightText: 2026 Kerrick Long
39
+ SPDX-License-Identifier: MIT-0
40
+ -->
36
41
  ```ruby
37
42
  Update.call(msg, model) -> Model
38
43
  ```
44
+ <!-- SPDX-SnippetEnd -->
39
45
 
40
46
  All logic previously in `Events.record` now lives here. The function never mutates, never draws, never performs IO.
41
47
 
@@ -47,6 +53,11 @@ Pure rendering logic. Views accept the immutable `AppModel` and draw to the scre
47
53
  ### 5. Runtime (`app.rb`)
48
54
  The MVU loop:
49
55
 
56
+ <!-- SPDX-SnippetBegin -->
57
+ <!--
58
+ SPDX-FileCopyrightText: 2026 Kerrick Long
59
+ SPDX-License-Identifier: MIT-0
60
+ -->
50
61
  ```ruby
51
62
  loop do
52
63
  tui.draw { |f| view.call(model, tui, f, f.area) }
@@ -55,6 +66,7 @@ loop do
55
66
  model = Update.call(msg, model)
56
67
  end
57
68
  ```
69
+ <!-- SPDX-SnippetEnd -->
58
70
 
59
71
  ## Library Features Showcased
60
72
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,6 +1,6 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
 
6
6
  # Color Picker Example
@@ -23,6 +23,11 @@ This app uses a **Strict Component-Based Architecture** where every UI element e
23
23
 
24
24
  Every component implements this duck-type interface:
25
25
 
26
+ <!-- SPDX-SnippetBegin -->
27
+ <!--
28
+ SPDX-FileCopyrightText: 2026 Kerrick Long
29
+ SPDX-License-Identifier: MIT-0
30
+ -->
26
31
  ```ruby
27
32
  # Renders the component into the given area
28
33
  # Caches `area` for hit testing
@@ -40,6 +45,7 @@ end
40
45
  def tick
41
46
  end
42
47
  ```
48
+ <!-- SPDX-SnippetEnd -->
43
49
 
44
50
  ### 1. The MainContainer (Orchestrator)
45
51
 
@@ -85,6 +91,11 @@ Components return semantic symbols instead of just `:consumed`:
85
91
 
86
92
  The `MainContainer` interprets these signals to coordinate cross-component communication:
87
93
 
94
+ <!-- SPDX-SnippetBegin -->
95
+ <!--
96
+ SPDX-FileCopyrightText: 2026 Kerrick Long
97
+ SPDX-License-Identifier: MIT-0
98
+ -->
88
99
  ```ruby
89
100
  result = @input.handle_event(event)
90
101
  case result
@@ -93,6 +104,7 @@ when :submitted
93
104
  return :consumed
94
105
  end
95
106
  ```
107
+ <!-- SPDX-SnippetEnd -->
96
108
 
97
109
  ### ⏱️ Lifecycle Hooks (`tick`)
98
110
 
@@ -109,9 +121,15 @@ Read this example if you are trying to solve:
109
121
 
110
122
  ## Usage
111
123
 
124
+ <!-- SPDX-SnippetBegin -->
125
+ <!--
126
+ SPDX-FileCopyrightText: 2026 Kerrick Long
127
+ SPDX-License-Identifier: MIT-0
128
+ -->
112
129
  ```bash
113
130
  ruby examples/app_color_picker/app.rb
114
131
  ```
132
+ <!-- SPDX-SnippetEnd -->
115
133
 
116
134
  - Type a hex code (e.g., `#FF0055`) or color name (`cyan`).
117
135
  - Press `Enter` to generate the palette.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7