ratatui_ruby 0.4.0 → 0.5.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 (351) 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 +87 -171
  7. data/CHANGELOG.md +38 -1
  8. data/README.md +8 -3
  9. data/REUSE.toml +20 -0
  10. data/doc/application_architecture.md +105 -45
  11. data/doc/application_testing.md +5 -3
  12. data/doc/contributors/design/ruby_frontend.md +9 -5
  13. data/doc/contributors/developing_examples.md +76 -18
  14. data/doc/contributors/documentation_style.md +7 -0
  15. data/doc/contributors/index.md +2 -0
  16. data/doc/event_handling.md +10 -4
  17. data/doc/images/app_all_events.png +0 -0
  18. data/doc/images/app_color_picker.png +0 -0
  19. data/doc/images/verify_readme_usage.png +0 -0
  20. data/doc/images/widget_barchart_demo.png +0 -0
  21. data/doc/images/widget_block_padding.png +0 -0
  22. data/doc/images/widget_block_titles.png +0 -0
  23. data/doc/images/widget_box_demo.png +0 -0
  24. data/doc/images/widget_calendar_demo.png +0 -0
  25. data/doc/images/widget_cell_demo.png +0 -0
  26. data/doc/images/widget_chart_demo.png +0 -0
  27. data/doc/images/widget_gauge_demo.png +0 -0
  28. data/doc/images/widget_layout_split.png +0 -0
  29. data/doc/images/widget_line_gauge_demo.png +0 -0
  30. data/doc/images/widget_list_demo.png +0 -0
  31. data/doc/images/widget_ratatui_logo_demo.png +0 -0
  32. data/doc/images/widget_ratatui_mascot_demo.png +0 -0
  33. data/doc/images/widget_render.png +0 -0
  34. data/doc/images/widget_scrollbar_demo.png +0 -0
  35. data/doc/images/widget_sparkline_demo.png +0 -0
  36. data/doc/images/widget_style_colors.png +0 -0
  37. data/doc/images/widget_table_flex.png +0 -0
  38. data/doc/images/widget_tabs_demo.png +0 -0
  39. data/doc/interactive_design.md +25 -30
  40. data/doc/quickstart.md +147 -120
  41. data/examples/app_all_events/README.md +81 -0
  42. data/examples/app_all_events/app.rb +93 -0
  43. data/examples/app_all_events/model/event_color_cycle.rb +41 -0
  44. data/examples/app_all_events/model/event_entry.rb +75 -0
  45. data/examples/app_all_events/model/events.rb +180 -0
  46. data/examples/app_all_events/model/highlight.rb +57 -0
  47. data/examples/app_all_events/model/timestamp.rb +54 -0
  48. data/examples/app_all_events/test/snapshots/after_focus_lost.txt +24 -0
  49. data/examples/app_all_events/test/snapshots/after_focus_regained.txt +24 -0
  50. data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +24 -0
  51. data/examples/app_all_events/test/snapshots/after_key_a.txt +24 -0
  52. data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +24 -0
  53. data/examples/app_all_events/test/snapshots/after_mouse_click.txt +24 -0
  54. data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +24 -0
  55. data/examples/app_all_events/test/snapshots/after_multiple_events.txt +24 -0
  56. data/examples/app_all_events/test/snapshots/after_paste.txt +24 -0
  57. data/examples/app_all_events/test/snapshots/after_resize.txt +24 -0
  58. data/examples/app_all_events/test/snapshots/after_right_click.txt +24 -0
  59. data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +24 -0
  60. data/examples/app_all_events/test/snapshots/initial_state.txt +24 -0
  61. data/examples/app_all_events/view/app_view.rb +78 -0
  62. data/examples/app_all_events/view/controls_view.rb +50 -0
  63. data/examples/app_all_events/view/counts_view.rb +55 -0
  64. data/examples/app_all_events/view/live_view.rb +69 -0
  65. data/examples/app_all_events/view/log_view.rb +60 -0
  66. data/examples/app_all_events/view.rb +7 -0
  67. data/examples/app_all_events/view_state.rb +42 -0
  68. data/examples/app_color_picker/README.md +94 -0
  69. data/examples/app_color_picker/app.rb +112 -0
  70. data/examples/app_color_picker/clipboard.rb +84 -0
  71. data/examples/app_color_picker/color.rb +191 -0
  72. data/examples/app_color_picker/copy_dialog.rb +170 -0
  73. data/examples/app_color_picker/harmony.rb +56 -0
  74. data/examples/app_color_picker/input.rb +142 -0
  75. data/examples/app_color_picker/palette.rb +80 -0
  76. data/examples/app_color_picker/scene.rb +201 -0
  77. data/examples/{login_form → app_login_form}/app.rb +39 -42
  78. data/examples/{map_demo → app_map_demo}/app.rb +24 -21
  79. data/examples/{table_select → app_table_select}/app.rb +68 -65
  80. data/examples/{quickstart_dsl → verify_quickstart_dsl}/app.rb +15 -6
  81. data/examples/verify_quickstart_layout/app.rb +69 -0
  82. data/examples/{quickstart_lifecycle → verify_quickstart_lifecycle}/app.rb +19 -10
  83. data/examples/verify_readme_usage/app.rb +34 -0
  84. data/examples/widget_barchart_demo/app.rb +238 -0
  85. data/examples/{block_padding → widget_block_padding}/app.rb +17 -13
  86. data/examples/{block_titles → widget_block_titles}/app.rb +25 -17
  87. data/examples/{box_demo → widget_box_demo}/app.rb +99 -65
  88. data/examples/widget_calendar_demo/app.rb +109 -0
  89. data/examples/widget_cell_demo/app.rb +104 -0
  90. data/examples/widget_chart_demo/app.rb +213 -0
  91. data/examples/widget_gauge_demo/app.rb +212 -0
  92. data/examples/widget_layout_split/app.rb +246 -0
  93. data/examples/widget_line_gauge_demo/app.rb +217 -0
  94. data/examples/widget_list_demo/app.rb +382 -0
  95. data/examples/widget_list_styles/app.rb +141 -0
  96. data/examples/widget_popup_demo/app.rb +104 -0
  97. data/examples/widget_ratatui_logo_demo/app.rb +103 -0
  98. data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
  99. data/examples/widget_rect/app.rb +205 -0
  100. data/examples/widget_render/app.rb +184 -0
  101. data/examples/widget_rich_text/app.rb +137 -0
  102. data/examples/widget_scroll_text/app.rb +108 -0
  103. data/examples/widget_scrollbar_demo/app.rb +153 -0
  104. data/examples/widget_sparkline_demo/app.rb +274 -0
  105. data/examples/widget_style_colors/app.rb +19 -21
  106. data/examples/widget_table_flex/app.rb +95 -0
  107. data/examples/widget_tabs_demo/app.rb +167 -0
  108. data/ext/ratatui_ruby/Cargo.lock +1 -1
  109. data/ext/ratatui_ruby/Cargo.toml +1 -1
  110. data/ext/ratatui_ruby/src/events.rs +121 -36
  111. data/ext/ratatui_ruby/src/frame.rs +115 -0
  112. data/ext/ratatui_ruby/src/lib.rs +79 -26
  113. data/ext/ratatui_ruby/src/rendering.rs +8 -4
  114. data/ext/ratatui_ruby/src/style.rs +138 -57
  115. data/ext/ratatui_ruby/src/terminal.rs +5 -9
  116. data/ext/ratatui_ruby/src/text.rs +13 -6
  117. data/ext/ratatui_ruby/src/widgets/barchart.rs +56 -54
  118. data/ext/ratatui_ruby/src/widgets/block.rs +7 -6
  119. data/ext/ratatui_ruby/src/widgets/canvas.rs +21 -3
  120. data/ext/ratatui_ruby/src/widgets/chart.rs +20 -10
  121. data/ext/ratatui_ruby/src/widgets/layout.rs +9 -4
  122. data/ext/ratatui_ruby/src/widgets/list.rs +32 -9
  123. data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
  124. data/ext/ratatui_ruby/src/widgets/paragraph.rs +1 -1
  125. data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +19 -8
  126. data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +17 -10
  127. data/ext/ratatui_ruby/src/widgets/scrollbar.rs +4 -2
  128. data/ext/ratatui_ruby/src/widgets/sparkline.rs +14 -11
  129. data/ext/ratatui_ruby/src/widgets/table.rs +8 -4
  130. data/ext/ratatui_ruby/src/widgets/tabs.rs +11 -11
  131. data/lib/ratatui_ruby/cell.rb +3 -3
  132. data/lib/ratatui_ruby/event/key.rb +1 -1
  133. data/lib/ratatui_ruby/event/none.rb +43 -0
  134. data/lib/ratatui_ruby/event.rb +56 -4
  135. data/lib/ratatui_ruby/frame.rb +87 -0
  136. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +11 -11
  137. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +1 -5
  138. data/lib/ratatui_ruby/schema/bar_chart.rb +217 -217
  139. data/lib/ratatui_ruby/schema/block.rb +163 -168
  140. data/lib/ratatui_ruby/schema/calendar.rb +66 -67
  141. data/lib/ratatui_ruby/schema/canvas.rb +63 -63
  142. data/lib/ratatui_ruby/schema/center.rb +46 -46
  143. data/lib/ratatui_ruby/schema/chart.rb +135 -143
  144. data/lib/ratatui_ruby/schema/clear.rb +42 -42
  145. data/lib/ratatui_ruby/schema/constraint.rb +76 -76
  146. data/lib/ratatui_ruby/schema/cursor.rb +25 -25
  147. data/lib/ratatui_ruby/schema/gauge.rb +53 -53
  148. data/lib/ratatui_ruby/schema/layout.rb +87 -87
  149. data/lib/ratatui_ruby/schema/line_gauge.rb +62 -62
  150. data/lib/ratatui_ruby/schema/list.rb +86 -84
  151. data/lib/ratatui_ruby/schema/overlay.rb +31 -31
  152. data/lib/ratatui_ruby/schema/paragraph.rb +80 -80
  153. data/lib/ratatui_ruby/schema/ratatui_logo.rb +10 -6
  154. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +10 -5
  155. data/lib/ratatui_ruby/schema/rect.rb +60 -60
  156. data/lib/ratatui_ruby/schema/scrollbar.rb +119 -119
  157. data/lib/ratatui_ruby/schema/shape/label.rb +1 -1
  158. data/lib/ratatui_ruby/schema/sparkline.rb +111 -110
  159. data/lib/ratatui_ruby/schema/style.rb +46 -46
  160. data/lib/ratatui_ruby/schema/table.rb +112 -119
  161. data/lib/ratatui_ruby/schema/tabs.rb +66 -67
  162. data/lib/ratatui_ruby/session/autodoc.rb +417 -0
  163. data/lib/ratatui_ruby/session.rb +40 -23
  164. data/lib/ratatui_ruby/test_helper.rb +185 -19
  165. data/lib/ratatui_ruby/version.rb +1 -1
  166. data/lib/ratatui_ruby.rb +65 -39
  167. data/{examples/sparkline_demo → sig/examples/app_all_events}/app.rbs +3 -2
  168. data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
  169. data/sig/examples/app_all_events/model/events.rbs +15 -0
  170. data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
  171. data/sig/examples/app_all_events/view/app_view.rbs +8 -0
  172. data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
  173. data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
  174. data/sig/examples/app_all_events/view/live_view.rbs +6 -0
  175. data/sig/examples/app_all_events/view/log_view.rbs +6 -0
  176. data/sig/examples/app_all_events/view.rbs +8 -0
  177. data/sig/examples/app_all_events/view_state.rbs +15 -0
  178. data/{examples/list_demo → sig/examples/app_color_picker}/app.rbs +2 -2
  179. data/sig/examples/app_login_form/app.rbs +11 -0
  180. data/sig/examples/app_map_demo/app.rbs +11 -0
  181. data/sig/examples/app_table_select/app.rbs +11 -0
  182. data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
  183. data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
  184. data/sig/examples/verify_readme_usage/app.rbs +11 -0
  185. data/sig/examples/widget_block_padding/app.rbs +11 -0
  186. data/sig/examples/widget_block_titles/app.rbs +11 -0
  187. data/sig/examples/widget_box_demo/app.rbs +11 -0
  188. data/sig/examples/widget_calendar_demo/app.rbs +11 -0
  189. data/sig/examples/widget_cell_demo/app.rbs +11 -0
  190. data/sig/examples/widget_chart_demo/app.rbs +11 -0
  191. data/{examples/gauge_demo → sig/examples/widget_gauge_demo}/app.rbs +4 -0
  192. data/sig/examples/widget_layout_split/app.rbs +10 -0
  193. data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
  194. data/sig/examples/widget_list_demo/app.rbs +12 -0
  195. data/sig/examples/widget_list_styles/app.rbs +11 -0
  196. data/sig/examples/widget_popup_demo/app.rbs +11 -0
  197. data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
  198. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
  199. data/sig/examples/widget_rect/app.rbs +12 -0
  200. data/sig/examples/widget_render/app.rbs +10 -0
  201. data/sig/examples/widget_rich_text/app.rbs +11 -0
  202. data/sig/examples/widget_scroll_text/app.rbs +11 -0
  203. data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
  204. data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
  205. data/{examples → sig/examples}/widget_style_colors/app.rbs +1 -1
  206. data/sig/examples/widget_table_flex/app.rbs +11 -0
  207. data/sig/ratatui_ruby/frame.rbs +9 -0
  208. data/sig/ratatui_ruby/ratatui_ruby.rbs +3 -2
  209. data/sig/ratatui_ruby/schema/draw.rbs +4 -0
  210. data/sig/ratatui_ruby/schema/layout.rbs +1 -1
  211. data/sig/ratatui_ruby/session.rbs +94 -0
  212. data/tasks/autodoc/inventory.rb +61 -0
  213. data/tasks/autodoc/member.rb +56 -0
  214. data/tasks/autodoc/name.rb +19 -0
  215. data/tasks/autodoc/notice.rb +26 -0
  216. data/tasks/autodoc/rbs.rb +38 -0
  217. data/tasks/autodoc/rdoc.rb +45 -0
  218. data/tasks/autodoc.rake +47 -0
  219. data/tasks/bump/history.rb +2 -2
  220. data/tasks/doc.rake +600 -6
  221. data/tasks/example_viewer.html.erb +172 -0
  222. data/tasks/lint.rake +8 -4
  223. data/tasks/resources/index.html.erb +6 -0
  224. data/tasks/sourcehut.rake +4 -4
  225. data/tasks/terminal_preview/app_screenshot.rb +1 -3
  226. data/tasks/terminal_preview/crash_report.rb +7 -9
  227. data/tasks/terminal_preview/launcher_script.rb +4 -6
  228. data/tasks/terminal_preview/preview_collection.rb +4 -6
  229. data/tasks/terminal_preview/safety_confirmation.rb +3 -5
  230. data/tasks/terminal_preview/saved_screenshot.rb +7 -9
  231. data/tasks/terminal_preview/terminal_window.rb +7 -9
  232. data/tasks/test.rake +1 -1
  233. data/tasks/website/index_page.rb +3 -3
  234. data/tasks/website/version.rb +10 -10
  235. data/tasks/website/version_menu.rb +10 -12
  236. data/tasks/website/versioned_documentation.rb +49 -17
  237. data/tasks/website/website.rb +6 -8
  238. data/tasks/website.rake +4 -4
  239. metadata +156 -125
  240. data/LICENSES/BSD-2-Clause.txt +0 -9
  241. data/doc/contributors/better_dx.md +0 -543
  242. data/doc/contributors/example_analysis.md +0 -82
  243. data/doc/images/all_events.png +0 -0
  244. data/doc/images/block_padding.png +0 -0
  245. data/doc/images/block_titles.png +0 -0
  246. data/doc/images/box_demo.png +0 -0
  247. data/doc/images/calendar_demo.png +0 -0
  248. data/doc/images/cell_demo.png +0 -0
  249. data/doc/images/chart_demo.png +0 -0
  250. data/doc/images/flex_layout.png +0 -0
  251. data/doc/images/gauge_demo.png +0 -0
  252. data/doc/images/line_gauge_demo.png +0 -0
  253. data/doc/images/list_demo.png +0 -0
  254. data/doc/images/readme_usage.png +0 -0
  255. data/doc/images/scrollbar_demo.png +0 -0
  256. data/doc/images/sparkline_demo.png +0 -0
  257. data/doc/images/table_flex.png +0 -0
  258. data/examples/all_events/app.rb +0 -169
  259. data/examples/all_events/app.rbs +0 -7
  260. data/examples/all_events/test_app.rb +0 -139
  261. data/examples/analytics/app.rb +0 -258
  262. data/examples/analytics/app.rbs +0 -7
  263. data/examples/analytics/test_app.rb +0 -132
  264. data/examples/block_padding/app.rbs +0 -7
  265. data/examples/block_padding/test_app.rb +0 -31
  266. data/examples/block_titles/app.rbs +0 -7
  267. data/examples/block_titles/test_app.rb +0 -34
  268. data/examples/box_demo/app.rbs +0 -7
  269. data/examples/box_demo/test_app.rb +0 -88
  270. data/examples/calendar_demo/app.rb +0 -101
  271. data/examples/calendar_demo/app.rbs +0 -7
  272. data/examples/calendar_demo/test_app.rb +0 -108
  273. data/examples/cell_demo/app.rb +0 -108
  274. data/examples/cell_demo/app.rbs +0 -7
  275. data/examples/cell_demo/test_app.rb +0 -36
  276. data/examples/chart_demo/app.rb +0 -203
  277. data/examples/chart_demo/app.rbs +0 -7
  278. data/examples/chart_demo/test_app.rb +0 -102
  279. data/examples/custom_widget/app.rb +0 -51
  280. data/examples/custom_widget/app.rbs +0 -7
  281. data/examples/custom_widget/test_app.rb +0 -30
  282. data/examples/flex_layout/app.rb +0 -156
  283. data/examples/flex_layout/app.rbs +0 -7
  284. data/examples/flex_layout/test_app.rb +0 -65
  285. data/examples/gauge_demo/app.rb +0 -182
  286. data/examples/gauge_demo/test_app.rb +0 -120
  287. data/examples/hit_test/app.rb +0 -175
  288. data/examples/hit_test/app.rbs +0 -7
  289. data/examples/hit_test/test_app.rb +0 -102
  290. data/examples/line_gauge_demo/app.rb +0 -190
  291. data/examples/line_gauge_demo/app.rbs +0 -7
  292. data/examples/line_gauge_demo/test_app.rb +0 -129
  293. data/examples/list_demo/app.rb +0 -253
  294. data/examples/list_demo/test_app.rb +0 -237
  295. data/examples/list_styles/app.rb +0 -140
  296. data/examples/list_styles/app.rbs +0 -7
  297. data/examples/list_styles/test_app.rb +0 -157
  298. data/examples/login_form/app.rbs +0 -7
  299. data/examples/login_form/test_app.rb +0 -51
  300. data/examples/map_demo/app.rbs +0 -7
  301. data/examples/map_demo/test_app.rb +0 -149
  302. data/examples/mouse_events/app.rb +0 -97
  303. data/examples/mouse_events/app.rbs +0 -7
  304. data/examples/mouse_events/test_app.rb +0 -53
  305. data/examples/popup_demo/app.rb +0 -103
  306. data/examples/popup_demo/app.rbs +0 -7
  307. data/examples/popup_demo/test_app.rb +0 -54
  308. data/examples/quickstart_dsl/app.rbs +0 -7
  309. data/examples/quickstart_dsl/test_app.rb +0 -29
  310. data/examples/quickstart_lifecycle/app.rbs +0 -7
  311. data/examples/quickstart_lifecycle/test_app.rb +0 -29
  312. data/examples/ratatui_logo_demo/app.rb +0 -79
  313. data/examples/ratatui_logo_demo/app.rbs +0 -7
  314. data/examples/ratatui_logo_demo/test_app.rb +0 -51
  315. data/examples/ratatui_mascot_demo/app.rb +0 -84
  316. data/examples/ratatui_mascot_demo/app.rbs +0 -7
  317. data/examples/ratatui_mascot_demo/test_app.rb +0 -47
  318. data/examples/readme_usage/app.rb +0 -29
  319. data/examples/readme_usage/app.rbs +0 -7
  320. data/examples/readme_usage/test_app.rb +0 -29
  321. data/examples/rich_text/app.rb +0 -141
  322. data/examples/rich_text/app.rbs +0 -7
  323. data/examples/rich_text/test_app.rb +0 -166
  324. data/examples/scroll_text/app.rb +0 -103
  325. data/examples/scroll_text/app.rbs +0 -7
  326. data/examples/scroll_text/test_app.rb +0 -110
  327. data/examples/scrollbar_demo/app.rb +0 -143
  328. data/examples/scrollbar_demo/app.rbs +0 -7
  329. data/examples/scrollbar_demo/test_app.rb +0 -77
  330. data/examples/sparkline_demo/app.rb +0 -240
  331. data/examples/sparkline_demo/test_app.rb +0 -107
  332. data/examples/table_flex/app.rb +0 -65
  333. data/examples/table_flex/app.rbs +0 -7
  334. data/examples/table_flex/test_app.rb +0 -36
  335. data/examples/table_select/app.rbs +0 -7
  336. data/examples/table_select/test_app.rb +0 -180
  337. data/examples/widget_style_colors/test_app.rb +0 -48
  338. /data/doc/images/{analytics.png → app_analytics.png} +0 -0
  339. /data/doc/images/{custom_widget.png → app_custom_widget.png} +0 -0
  340. /data/doc/images/{login_form.png → app_login_form.png} +0 -0
  341. /data/doc/images/{map_demo.png → app_map_demo.png} +0 -0
  342. /data/doc/images/{mouse_events.png → app_mouse_events.png} +0 -0
  343. /data/doc/images/{table_select.png → app_table_select.png} +0 -0
  344. /data/doc/images/{quickstart_dsl.png → verify_quickstart_dsl.png} +0 -0
  345. /data/doc/images/{ratatui_logo_demo.png → verify_quickstart_layout.png} +0 -0
  346. /data/doc/images/{quickstart_lifecycle.png → verify_quickstart_lifecycle.png} +0 -0
  347. /data/doc/images/{list_styles.png → widget_list_styles.png} +0 -0
  348. /data/doc/images/{popup_demo.png → widget_popup_demo.png} +0 -0
  349. /data/doc/images/{hit_test.png → widget_rect.png} +0 -0
  350. /data/doc/images/{rich_text.png → widget_rich_text.png} +0 -0
  351. /data/doc/images/{scroll_text.png → widget_scroll_text.png} +0 -0
@@ -4,192 +4,187 @@
4
4
  # SPDX-License-Identifier: AGPL-3.0-or-later
5
5
 
6
6
  module RatatuiRuby
7
- # Defines the visual container for a widget.
7
+ # Defines the visual container for a widget.
8
+ #
9
+ # Widgets often float in void. Without boundaries, interfaces become a chaotic mess of text. Users need structure to parse information.
10
+ #
11
+ # This widget creates that structure. It wraps content in borders. It labels sections with titles. It paints the background.
12
+ #
13
+ # Use blocks to define distinct areas. Group related information. Create a visual hierarchy that guides the user's eye.
14
+ #
15
+ # {rdoc-image:/doc/images/widget_box_demo.png}[link:/examples/widget_box_demo/app_rb.html]
16
+ #
17
+ # === Example
18
+ #
19
+ # Run the interactive demo from the terminal:
20
+ #
21
+ # ruby examples/widget_box_demo/app.rb
22
+ class Block < Data.define(:title, :titles, :title_alignment, :title_style, :borders, :border_color, :border_style, :border_type, :border_set, :style, :padding, :children)
23
+ ##
24
+ # :attr_reader: title
25
+ # The main title displayed on the top border.
8
26
  #
9
- # Widgets often float in void. Without boundaries, interfaces become a chaotic mess of text. Users need structure to parse information.
27
+ # === Example
10
28
  #
11
- # This widget creates that structure. It wraps content in borders. It labels sections with titles. It paints the background.
12
- #
13
- # Use blocks to define distinct areas. Group related information. Create a visual hierarchy that guides the user's eye.
29
+ # Block.new(title: "Main").title # => "Main"
30
+
31
+ ##
32
+ # :attr_reader: titles
33
+ # Additional titles for complex labeling.
14
34
  #
15
- # === Examples
35
+ # Each title can be a <tt>String</tt> or a <tt>Hash</tt> with keys <tt>:content</tt>, <tt>:alignment</tt>, <tt>:position</tt> (<tt>:top</tt> or <tt>:bottom</tt>), and <tt>:style</tt>.
16
36
  #
17
- # # A simple bordered block
18
- # Block.new(borders: [:all], title: "Logs")
37
+ # === Example
19
38
  #
20
- # # A complex block with styling and padding
21
- # Block.new(
22
- # title: "Status",
23
- # borders: [:left, :right],
24
- # style: Style.new(fg: :yellow),
25
- # padding: [1, 1, 0, 0] # Left, Right, Top, Bottom
26
- # )
27
- class Block < Data.define(:title, :titles, :title_alignment, :title_style, :borders, :border_color, :border_style, :border_type, :border_set, :style, :padding, :children)
28
- ##
29
- # :attr_reader: title
30
- # The main title displayed on the top border.
31
- #
32
- # === Example
33
- #
34
- # Block.new(title: "Main").title # => "Main"
39
+ # Block.new(titles: ["Top", { content: "Bottom", position: :bottom }]).titles
35
40
 
36
- ##
37
- # :attr_reader: titles
38
- # Additional titles for complex labeling.
39
- #
40
- # Each title can be a <tt>String</tt> or a <tt>Hash</tt> with keys <tt>:content</tt>, <tt>:alignment</tt>, <tt>:position</tt> (<tt>:top</tt> or <tt>:bottom</tt>), and <tt>:style</tt>.
41
- #
42
- # === Example
43
- #
44
- # Block.new(titles: ["Top", { content: "Bottom", position: :bottom }]).titles
45
-
46
- ##
47
- # :attr_reader: title_alignment
48
- # Alignment of the main title.
49
- #
50
- # One of <tt>:left</tt>, <tt>:center</tt>, or <tt>:right</tt>.
51
- #
52
- # === Example
53
- #
54
- # Block.new(title_alignment: :center).title_alignment # => :center
41
+ ##
42
+ # :attr_reader: title_alignment
43
+ # Alignment of the main title.
44
+ #
45
+ # One of <tt>:left</tt>, <tt>:center</tt>, or <tt>:right</tt>.
46
+ #
47
+ # === Example
48
+ #
49
+ # Block.new(title_alignment: :center).title_alignment # => :center
55
50
 
56
- ##
57
- # :attr_reader: title_style
58
- # Style applied to all titles if not overridden.
59
- #
60
- # === Example
61
- #
62
- # Block.new(title_style: Style.new(fg: :red)).title_style
51
+ ##
52
+ # :attr_reader: title_style
53
+ # Style applied to all titles if not overridden.
54
+ #
55
+ # === Example
56
+ #
57
+ # Block.new(title_style: Style.new(fg: :red)).title_style
63
58
 
64
- ##
65
- # :attr_reader: borders
66
- # Visible borders.
67
- #
68
- # An array containing any of <tt>:top</tt>, <tt>:bottom</tt>, <tt>:left</tt>, <tt>:right</tt>, or <tt>:all</tt>.
69
- #
70
- # === Example
71
- #
72
- # Block.new(borders: [:left, :right]).borders # => [:left, :right]
59
+ ##
60
+ # :attr_reader: borders
61
+ # Visible borders.
62
+ #
63
+ # An array containing any of <tt>:top</tt>, <tt>:bottom</tt>, <tt>:left</tt>, <tt>:right</tt>, or <tt>:all</tt>.
64
+ #
65
+ # === Example
66
+ #
67
+ # Block.new(borders: [:left, :right]).borders # => [:left, :right]
73
68
 
74
- ##
75
- # :attr_reader: border_color
76
- # Color of the border lines.
77
- #
78
- # Deprecated: Use <tt>border_style:</tt> instead for full style support.
69
+ ##
70
+ # :attr_reader: border_color
71
+ # Color of the border lines.
72
+ #
73
+ # Deprecated: Use <tt>border_style:</tt> instead for full style support.
79
74
 
80
- ##
81
- # :attr_reader: border_style
82
- # Full style (colors/modifiers) for the border lines.
83
- #
84
- # A Style object or Hash with <tt>:fg</tt>, <tt>:bg</tt>, and <tt>:modifiers</tt>.
85
- # This allows borders to be bold, italic, colored, etc. If both <tt>border_color</tt>
86
- # and <tt>border_style</tt> are provided, <tt>border_style</tt> takes precedence.
75
+ ##
76
+ # :attr_reader: border_style
77
+ # Full style (colors/modifiers) for the border lines.
78
+ #
79
+ # A Style object or Hash with <tt>:fg</tt>, <tt>:bg</tt>, and <tt>:modifiers</tt>.
80
+ # This allows borders to be bold, italic, colored, etc. If both <tt>border_color</tt>
81
+ # and <tt>border_style</tt> are provided, <tt>border_style</tt> takes precedence.
87
82
 
88
- ##
89
- # :attr_reader: border_type
90
- # Visual style of the border lines.
91
- #
92
- # One of <tt>:plain</tt>, <tt>:rounded</tt>, <tt>:double</tt>, <tt>:thick</tt>, etc.
83
+ ##
84
+ # :attr_reader: border_type
85
+ # Visual style of the border lines.
86
+ #
87
+ # One of <tt>:plain</tt>, <tt>:rounded</tt>, <tt>:double</tt>, <tt>:thick</tt>, etc.
93
88
 
94
- ##
95
- # :attr_reader: border_set
96
- # Custom characters for the border lines.
97
- #
98
- # A Hash with keys defining the characters for the borders.
99
- # Keys: <tt>:top_left</tt>, <tt>:top_right</tt>, <tt>:bottom_left</tt>, <tt>:bottom_right</tt>,
100
- # <tt>:vertical_left</tt>, <tt>:vertical_right</tt>, <tt>:horizontal_top</tt>, <tt>:horizontal_bottom</tt>.
101
- #
102
- # Providing this overrides <tt>border_type</tt>.
103
- #
104
- #
105
- # === Example
106
- #
107
- # Block.new(border_set: { top_left: "1", top_right: "2", bottom_left: "3", bottom_right: "4", vertical_left: "5", vertical_right: "6", horizontal_top: "7", horizontal_bottom: "8" })
89
+ ##
90
+ # :attr_reader: border_set
91
+ # Custom characters for the border lines.
92
+ #
93
+ # A Hash with keys defining the characters for the borders.
94
+ # Keys: <tt>:top_left</tt>, <tt>:top_right</tt>, <tt>:bottom_left</tt>, <tt>:bottom_right</tt>,
95
+ # <tt>:vertical_left</tt>, <tt>:vertical_right</tt>, <tt>:horizontal_top</tt>, <tt>:horizontal_bottom</tt>.
96
+ #
97
+ # Providing this overrides <tt>border_type</tt>.
98
+ #
99
+ #
100
+ # === Example
101
+ #
102
+ # Block.new(border_set: { top_left: "1", top_right: "2", bottom_left: "3", bottom_right: "4", vertical_left: "5", vertical_right: "6", horizontal_top: "7", horizontal_bottom: "8" })
108
103
 
109
- ##
110
- # :attr_reader: style
111
- # Base style (colors/modifiers) for the block content.
104
+ ##
105
+ # :attr_reader: style
106
+ # Base style (colors/modifiers) for the block content.
112
107
 
113
- ##
114
- # :attr_reader: padding
115
- # Inner padding.
116
- #
117
- # Can be a single <tt>Integer</tt> (uniform) or a 4-element <tt>Array</tt> (left, right, top, bottom).
118
- #
119
- # === Example
120
- #
121
- # Block.new(padding: 2).padding # => 2
122
- # Block.new(padding: [1, 1, 0, 0]).padding # => [1, 1, 0, 0]
108
+ ##
109
+ # :attr_reader: padding
110
+ # Inner padding.
111
+ #
112
+ # Can be a single <tt>Integer</tt> (uniform) or a 4-element <tt>Array</tt> (left, right, top, bottom).
113
+ #
114
+ # === Example
115
+ #
116
+ # Block.new(padding: 2).padding # => 2
117
+ # Block.new(padding: [1, 1, 0, 0]).padding # => [1, 1, 0, 0]
123
118
 
124
- ##
125
- # :attr_reader: children
126
- # Widgets to render inside the block (optional).
127
- #
128
- # When provided, each child widget is rendered within the block's area.
129
- #
130
- # === Example
131
- #
132
- # Block.new(
133
- # title: "Content",
134
- # borders: [:all],
135
- # children: [Paragraph.new(text: "Hello")]
136
- # )
119
+ ##
120
+ # :attr_reader: children
121
+ # Widgets to render inside the block (optional).
122
+ #
123
+ # When provided, each child widget is rendered within the block's area.
124
+ #
125
+ # === Example
126
+ #
127
+ # Block.new(
128
+ # title: "Content",
129
+ # borders: [:all],
130
+ # children: [Paragraph.new(text: "Hello")]
131
+ # )
137
132
 
138
- # Creates a new Block.
139
- #
140
- # [title]
141
- # Main title string (optional).
142
- # [titles]
143
- # Array of additional titles (optional).
144
- # [title_alignment]
145
- # Alignment symbol: <tt>:left</tt> (default), <tt>:center</tt>, <tt>:right</tt>.
146
- # [title_style]
147
- # Base style for all titles (optional).
148
- # [borders]
149
- # Array of borders to show: <tt>:top</tt>, <tt>:bottom</tt>, <tt>:left</tt>, <tt>:right</tt>, or <tt>:all</tt> (default).
150
- # [border_color]
151
- # Color string or symbol (e.g., <tt>:red</tt>). Deprecated: use <tt>border_style</tt> instead.
152
- # [border_style]
153
- # Style object or Hash for the border lines.
154
- # [border_type]
155
- # Symbol: <tt>:plain</tt> (default), <tt>:rounded</tt>, <tt>:double</tt>, <tt>:thick</tt>, <tt>:hidden</tt>, <tt>:quadrant_inside</tt>, <tt>:quadrant_outside</tt>.
156
- # [border_set]
157
- # Hash: Custom characters for the border lines. Unique characters are interned (leaked) permanently, so avoid infinite dynamic variations.
158
- # [style]
159
- # Style object or Hash for the block's content area.
160
- # [padding]
161
- # Integer (uniform) or Array[4] (left, right, top, bottom).
162
- # [children]
163
- # Array of widgets to render inside the block (optional).
164
- def initialize(title: nil, titles: [], title_alignment: nil, title_style: nil, borders: [:all], border_color: nil, border_style: nil, border_type: nil, border_set: nil, style: nil, padding: 0, children: [])
165
- if border_set
166
- border_set = border_set.dup
167
- %i[top_left top_right bottom_left bottom_right vertical_left vertical_right horizontal_top horizontal_bottom].each do |long_key|
168
- short_key = long_key.to_s.split("_").map { |s| s[0] }.join
169
- if val = border_set.delete(short_key.to_sym) || border_set.delete(short_key)
170
- border_set[long_key] = val
171
- end
133
+ # Creates a new Block.
134
+ #
135
+ # [title]
136
+ # Main title string (optional).
137
+ # [titles]
138
+ # Array of additional titles (optional).
139
+ # [title_alignment]
140
+ # Alignment symbol: <tt>:left</tt> (default), <tt>:center</tt>, <tt>:right</tt>.
141
+ # [title_style]
142
+ # Base style for all titles (optional).
143
+ # [borders]
144
+ # Array of borders to show: <tt>:top</tt>, <tt>:bottom</tt>, <tt>:left</tt>, <tt>:right</tt>, or <tt>:all</tt> (default).
145
+ # [border_color]
146
+ # Color string or symbol (e.g., <tt>:red</tt>). Deprecated: use <tt>border_style</tt> instead.
147
+ # [border_style]
148
+ # Style object or Hash for the border lines.
149
+ # [border_type]
150
+ # Symbol: <tt>:plain</tt> (default), <tt>:rounded</tt>, <tt>:double</tt>, <tt>:thick</tt>, <tt>:hidden</tt>, <tt>:quadrant_inside</tt>, <tt>:quadrant_outside</tt>.
151
+ # [border_set]
152
+ # Hash: Custom characters for the border lines. Unique characters are interned (leaked) permanently, so avoid infinite dynamic variations.
153
+ # [style]
154
+ # Style object or Hash for the block's content area.
155
+ # [padding]
156
+ # Integer (uniform) or Array[4] (left, right, top, bottom).
157
+ # [children]
158
+ # Array of widgets to render inside the block (optional).
159
+ def initialize(title: nil, titles: [], title_alignment: nil, title_style: nil, borders: [:all], border_color: nil, border_style: nil, border_type: nil, border_set: nil, style: nil, padding: 0, children: [])
160
+ if border_set
161
+ border_set = border_set.dup
162
+ %i[top_left top_right bottom_left bottom_right vertical_left vertical_right horizontal_top horizontal_bottom].each do |long_key|
163
+ short_key = long_key.to_s.split("_").map { |s| s[0] }.join
164
+ if (val = border_set.delete(short_key.to_sym) || border_set.delete(short_key))
165
+ border_set[long_key] = val
172
166
  end
173
167
  end
174
- coerced_padding = if padding.is_a?(Array)
175
- padding.map { |v| Integer(v) }
176
- else
177
- Integer(padding)
178
- end
179
- super(
180
- title: title,
181
- titles: titles,
182
- title_alignment: title_alignment,
183
- title_style: title_style,
184
- borders: borders,
185
- border_color: border_color,
186
- border_style: border_style,
187
- border_type: border_type,
188
- border_set: border_set,
189
- style: style,
190
- padding: coerced_padding,
191
- children: children
192
- )
193
168
  end
169
+ coerced_padding = if padding.is_a?(Array)
170
+ padding.map { |v| Integer(v) }
171
+ else
172
+ Integer(padding)
173
+ end
174
+ super(
175
+ title:,
176
+ titles:,
177
+ title_alignment:,
178
+ title_style:,
179
+ borders:,
180
+ border_color:,
181
+ border_style:,
182
+ border_type:,
183
+ border_set:,
184
+ style:,
185
+ padding: coerced_padding,
186
+ children:
187
+ )
194
188
  end
189
+ end
195
190
  end
@@ -4,80 +4,79 @@
4
4
  # SPDX-License-Identifier: AGPL-3.0-or-later
5
5
 
6
6
  module RatatuiRuby
7
- # Displays a monthly calendar grid.
8
- #
9
- # Dates are complex. Rendering them in a grid requires calculation of leap years, month lengths, and day-of-week offsets.
10
- # Use this widget to skip the boilerplate.
11
- #
12
- # This widget renders a standard monthly view. It highlights the current date. It structures time.
13
- #
14
- # Use it for date pickers, schedulers, or logs.
15
- #
16
- # === Examples
17
- #
18
- # Calendar.new(
19
- # year: 2025,
20
- # month: 12,
21
- # default_style: Style.new(fg: :white),
22
- # header_style: Style.new(fg: :yellow, modifiers: [:bold])
23
- # )
24
- class Calendar < Data.define(:year, :month, :events, :default_style, :header_style, :block, :show_weekdays_header, :show_surrounding, :show_month_header)
25
- ##
26
- # :attr_reader: year
27
- # The year to display (Integer).
7
+ # Displays a monthly calendar grid.
8
+ #
9
+ # Dates are complex. Rendering them in a grid requires calculation of leap years, month lengths, and day-of-week offsets.
10
+ # Use this widget to skip the boilerplate.
11
+ #
12
+ # This widget renders a standard monthly view. It highlights the current date. It structures time.
13
+ #
14
+ # Use it for date pickers, schedulers, or logs.
15
+ #
16
+ # {rdoc-image:/doc/images/widget_calendar_demo.png}[link:/examples/widget_calendar_demo/app_rb.html]
17
+ #
18
+ # === Example
19
+ #
20
+ # Run the interactive demo from the terminal:
21
+ #
22
+ # ruby examples/widget_calendar_demo/app.rb
23
+ class Calendar < Data.define(:year, :month, :events, :default_style, :header_style, :block, :show_weekdays_header, :show_surrounding, :show_month_header)
24
+ ##
25
+ # :attr_reader: year
26
+ # The year to display (Integer).
28
27
 
29
- ##
30
- # :attr_reader: month
31
- # The month to display (1–12).
28
+ ##
29
+ # :attr_reader: month
30
+ # The month to display (1–12).
32
31
 
33
- ##
34
- # :attr_reader: events
35
- # A Hash mapping Dates to Styles for event highlighting.
36
- # Keys must be `Date` objects (or objects responding to `day`, `month`, `year`).
37
- # Values must be `Style` objects.
32
+ ##
33
+ # :attr_reader: events
34
+ # A Hash mapping Dates to Styles for event highlighting.
35
+ # Keys must be `Date` objects (or objects responding to `day`, `month`, `year`).
36
+ # Values must be `Style` objects.
38
37
 
39
- ##
40
- # :attr_reader: default_style
41
- # Style for the days.
38
+ ##
39
+ # :attr_reader: default_style
40
+ # Style for the days.
42
41
 
43
- ##
44
- # :attr_reader: header_style
45
- # Style for the month name header.
42
+ ##
43
+ # :attr_reader: header_style
44
+ # Style for the month name header.
46
45
 
47
- ##
48
- # :attr_reader: block
49
- # Optional wrapping block.
46
+ ##
47
+ # :attr_reader: block
48
+ # Optional wrapping block.
50
49
 
51
- ##
52
- # :attr_reader: show_weekdays_header
53
- # Whether to show the weekday header (Mon, Tue, etc.).
50
+ ##
51
+ # :attr_reader: show_weekdays_header
52
+ # Whether to show the weekday header (Mon, Tue, etc.).
54
53
 
55
- ##
56
- # :attr_reader: show_surrounding
57
- # Style for dates from surrounding months. If <tt>nil</tt>, surrounding dates are hidden.
54
+ ##
55
+ # :attr_reader: show_surrounding
56
+ # Style for dates from surrounding months. If <tt>nil</tt>, surrounding dates are hidden.
58
57
 
59
- # Creates a new Calendar.
60
- #
61
- # [year] Integer.
62
- # [month] Integer.
63
- # [events] Hash<Date, Style>. Optional.
64
- # [default_style] Style.
65
- # [header_style] Style.
66
- # [block] Block.
67
- # [show_weekdays_header] Boolean. Whether to show the weekday header.
68
- # [show_surrounding] <tt>Style</tt> or <tt>nil</tt>. Style for surrounding month dates.
69
- def initialize(year:, month:, events: {}, default_style: nil, header_style: nil, block: nil, show_weekdays_header: true, show_surrounding: nil, show_month_header: false)
70
- super(
71
- year: Integer(year),
72
- month: Integer(month),
73
- events: events,
74
- default_style: default_style,
75
- header_style: header_style,
76
- block: block,
77
- show_weekdays_header: show_weekdays_header,
78
- show_surrounding: show_surrounding,
79
- show_month_header: show_month_header
80
- )
81
- end
58
+ # Creates a new Calendar.
59
+ #
60
+ # [year] Integer.
61
+ # [month] Integer.
62
+ # [events] Hash<Date, Style>. Optional.
63
+ # [default_style] Style.
64
+ # [header_style] Style.
65
+ # [block] Block.
66
+ # [show_weekdays_header] Boolean. Whether to show the weekday header.
67
+ # [show_surrounding] <tt>Style</tt> or <tt>nil</tt>. Style for surrounding month dates.
68
+ def initialize(year:, month:, events: {}, default_style: nil, header_style: nil, block: nil, show_weekdays_header: true, show_surrounding: nil, show_month_header: false)
69
+ super(
70
+ year: Integer(year),
71
+ month: Integer(month),
72
+ events:,
73
+ default_style:,
74
+ header_style:,
75
+ block:,
76
+ show_weekdays_header:,
77
+ show_surrounding:,
78
+ show_month_header:
79
+ )
82
80
  end
81
+ end
83
82
  end