ratatui_ruby 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.builds/ruby-3.2.yml +2 -2
- data/.builds/ruby-3.3.yml +2 -2
- data/.builds/ruby-3.4.yml +2 -2
- data/.builds/ruby-4.0.0.yml +2 -2
- data/.pre-commit-config.yaml +1 -1
- data/AGENTS.md +3 -3
- data/CHANGELOG.md +77 -1
- data/LICENSES/LGPL-3.0-or-later.txt +304 -0
- data/LICENSES/MIT-0.txt +16 -0
- data/README.md +33 -5
- data/Rakefile +1 -1
- data/doc/concepts/application_architecture.md +44 -3
- data/doc/concepts/application_testing.md +43 -1
- data/doc/concepts/async.md +32 -2
- data/doc/concepts/custom_widgets.md +247 -0
- data/doc/concepts/event_handling.md +32 -3
- data/doc/concepts/interactive_design.md +32 -2
- data/doc/contributors/auditing/parity.md +7 -1
- data/doc/contributors/design/ruby_frontend.md +85 -1
- data/doc/contributors/design/rust_backend.md +67 -1
- data/doc/contributors/developing_examples.md +56 -2
- data/doc/contributors/documentation_style.md +20 -3
- data/doc/contributors/future_work.md +169 -0
- data/doc/contributors/index.md +1 -1
- data/doc/contributors/v1.0.0_blockers.md +19 -185
- data/doc/getting_started/quickstart.md +22 -4
- data/doc/getting_started/why.md +1 -1
- data/doc/index.md +2 -1
- data/doc/troubleshooting/debugging.md +32 -2
- data/doc/troubleshooting/terminal_limitations.md +8 -2
- data/doc/troubleshooting/tui_output.md +42 -0
- data/examples/app_all_events/README.md +14 -2
- data/examples/app_all_events/app.rb +1 -1
- data/examples/app_all_events/model/app_model.rb +1 -1
- data/examples/app_all_events/model/event_color_cycle.rb +1 -1
- data/examples/app_all_events/model/event_entry.rb +1 -1
- data/examples/app_all_events/model/msg.rb +1 -1
- data/examples/app_all_events/model/timestamp.rb +1 -1
- data/examples/app_all_events/update.rb +1 -1
- data/examples/app_all_events/view/app_view.rb +1 -1
- data/examples/app_all_events/view/controls_view.rb +1 -1
- data/examples/app_all_events/view/counts_view.rb +1 -1
- data/examples/app_all_events/view/live_view.rb +1 -1
- data/examples/app_all_events/view/log_view.rb +1 -1
- data/examples/app_all_events/view.rb +1 -1
- data/examples/app_color_picker/README.md +20 -2
- data/examples/app_color_picker/app.rb +1 -1
- data/examples/app_color_picker/clipboard.rb +1 -1
- data/examples/app_color_picker/color.rb +1 -1
- data/examples/app_color_picker/controls.rb +1 -1
- data/examples/app_color_picker/copy_dialog.rb +1 -1
- data/examples/app_color_picker/export_pane.rb +1 -1
- data/examples/app_color_picker/harmony.rb +1 -1
- data/examples/app_color_picker/input.rb +1 -1
- data/examples/app_color_picker/main_container.rb +1 -1
- data/examples/app_color_picker/palette.rb +1 -1
- data/examples/app_login_form/README.md +8 -2
- data/examples/app_login_form/app.rb +1 -1
- data/examples/app_stateful_interaction/README.md +2 -2
- data/examples/app_stateful_interaction/app.rb +71 -17
- data/examples/timeout_demo.rb +1 -1
- data/examples/verify_quickstart_dsl/README.md +6 -0
- data/examples/verify_quickstart_dsl/app.rb +3 -3
- data/examples/verify_quickstart_layout/README.md +6 -0
- data/examples/verify_quickstart_layout/app.rb +3 -3
- data/examples/verify_quickstart_lifecycle/README.md +6 -0
- data/examples/verify_quickstart_lifecycle/app.rb +3 -3
- data/examples/verify_readme_usage/README.md +6 -0
- data/examples/verify_readme_usage/app.rb +3 -3
- data/examples/widget_barchart/README.md +6 -0
- data/examples/widget_barchart/app.rb +2 -2
- data/examples/widget_block/README.md +7 -1
- data/examples/widget_block/app.rb +2 -2
- data/examples/widget_box/README.md +6 -0
- data/examples/widget_box/app.rb +9 -6
- data/examples/widget_calendar/README.md +6 -0
- data/examples/widget_calendar/app.rb +2 -2
- data/examples/widget_canvas/README.md +4 -0
- data/examples/widget_canvas/app.rb +2 -2
- data/examples/widget_cell/README.md +6 -0
- data/examples/widget_cell/app.rb +2 -3
- data/examples/widget_center/README.md +4 -0
- data/examples/widget_center/app.rb +2 -2
- data/examples/widget_chart/README.md +6 -0
- data/examples/widget_chart/app.rb +2 -2
- data/examples/widget_gauge/README.md +6 -0
- data/examples/widget_gauge/app.rb +2 -2
- data/examples/widget_layout_split/README.md +6 -0
- data/examples/widget_layout_split/app.rb +9 -3
- data/examples/widget_line_gauge/README.md +6 -0
- data/examples/widget_line_gauge/app.rb +2 -2
- data/examples/widget_list/README.md +6 -0
- data/examples/widget_list/app.rb +2 -2
- data/examples/widget_map/README.md +8 -2
- data/examples/widget_map/app.rb +2 -2
- data/examples/widget_overlay/README.md +7 -1
- data/examples/widget_overlay/app.rb +2 -2
- data/examples/widget_popup/README.md +6 -0
- data/examples/widget_popup/app.rb +2 -2
- data/examples/widget_ratatui_logo/README.md +6 -0
- data/examples/widget_ratatui_logo/app.rb +2 -3
- data/examples/widget_ratatui_mascot/README.md +6 -0
- data/examples/widget_ratatui_mascot/app.rb +2 -2
- data/examples/widget_rect/README.md +12 -0
- data/examples/widget_rect/app.rb +40 -26
- data/examples/widget_render/README.md +6 -0
- data/examples/widget_render/app.rb +2 -2
- data/examples/widget_render/app.rbs +41 -0
- data/examples/widget_rich_text/README.md +6 -0
- data/examples/widget_rich_text/app.rb +2 -2
- data/examples/widget_scroll_text/README.md +6 -0
- data/examples/widget_scroll_text/app.rb +2 -2
- data/examples/widget_scrollbar/README.md +6 -0
- data/examples/widget_scrollbar/app.rb +2 -2
- data/examples/widget_sparkline/README.md +6 -0
- data/examples/widget_sparkline/app.rb +2 -2
- data/examples/widget_style_colors/README.md +6 -0
- data/examples/widget_style_colors/app.rb +2 -2
- data/examples/widget_table/README.md +8 -2
- data/examples/widget_table/app.rb +2 -2
- data/examples/widget_tabs/README.md +6 -0
- data/examples/widget_tabs/app.rb +2 -2
- data/examples/widget_text_width/README.md +6 -0
- data/examples/widget_text_width/app.rb +4 -4
- data/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/ext/ratatui_ruby/extconf.rb +2 -2
- data/ext/ratatui_ruby/src/events.rs +1 -0
- data/ext/ratatui_ruby/src/rendering.rs +1 -1
- data/ext/ratatui_ruby/src/style.rs +0 -8
- data/ext/ratatui_ruby/src/widgets/chart.rs +0 -118
- data/ext/ratatui_ruby/src/widgets/list_state.rs +36 -0
- data/lib/ratatui_ruby/buffer/cell.rb +34 -2
- data/lib/ratatui_ruby/buffer.rb +2 -2
- data/lib/ratatui_ruby/cell.rb +34 -2
- data/lib/ratatui_ruby/event/focus_gained.rb +26 -2
- data/lib/ratatui_ruby/event/focus_lost.rb +26 -2
- data/lib/ratatui_ruby/event/key/character.rb +18 -2
- data/lib/ratatui_ruby/event/key/media.rb +2 -2
- data/lib/ratatui_ruby/event/key/modifier.rb +10 -2
- data/lib/ratatui_ruby/event/key/navigation.rb +2 -2
- data/lib/ratatui_ruby/event/key/system.rb +2 -2
- data/lib/ratatui_ruby/event/key.rb +114 -2
- data/lib/ratatui_ruby/event/mouse.rb +42 -2
- data/lib/ratatui_ruby/event/none.rb +10 -2
- data/lib/ratatui_ruby/event/paste.rb +34 -2
- data/lib/ratatui_ruby/event/resize.rb +34 -2
- data/lib/ratatui_ruby/event/sync.rb +52 -0
- data/lib/ratatui_ruby/event.rb +32 -2
- data/lib/ratatui_ruby/frame.rb +74 -2
- data/lib/ratatui_ruby/layout/constraint.rb +193 -2
- data/lib/ratatui_ruby/layout/layout.rb +47 -2
- data/lib/ratatui_ruby/layout/rect.rb +403 -2
- data/lib/ratatui_ruby/layout.rb +2 -2
- data/lib/ratatui_ruby/list_state.rb +113 -2
- data/lib/ratatui_ruby/output_guard.rb +26 -3
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -2
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +2 -2
- data/lib/ratatui_ruby/schema/bar_chart.rb +50 -2
- data/lib/ratatui_ruby/schema/block.rb +21 -15
- data/lib/ratatui_ruby/schema/calendar.rb +2 -2
- data/lib/ratatui_ruby/schema/canvas.rb +10 -2
- data/lib/ratatui_ruby/schema/center.rb +10 -2
- data/lib/ratatui_ruby/schema/chart.rb +2 -28
- data/lib/ratatui_ruby/schema/clear.rb +10 -2
- data/lib/ratatui_ruby/schema/constraint.rb +58 -2
- data/lib/ratatui_ruby/schema/cursor.rb +10 -2
- data/lib/ratatui_ruby/schema/draw.rb +10 -2
- data/lib/ratatui_ruby/schema/gauge.rb +2 -2
- data/lib/ratatui_ruby/schema/layout.rb +18 -2
- data/lib/ratatui_ruby/schema/line_gauge.rb +2 -2
- data/lib/ratatui_ruby/schema/list.rb +10 -2
- data/lib/ratatui_ruby/schema/list_item.rb +10 -2
- data/lib/ratatui_ruby/schema/overlay.rb +10 -2
- data/lib/ratatui_ruby/schema/paragraph.rb +10 -2
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +2 -2
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +2 -2
- data/lib/ratatui_ruby/schema/rect.rb +58 -2
- data/lib/ratatui_ruby/schema/row.rb +10 -2
- data/lib/ratatui_ruby/schema/scrollbar.rb +2 -2
- data/lib/ratatui_ruby/schema/shape/label.rb +10 -2
- data/lib/ratatui_ruby/schema/sparkline.rb +10 -2
- data/lib/ratatui_ruby/schema/style.rb +18 -2
- data/lib/ratatui_ruby/schema/table.rb +2 -2
- data/lib/ratatui_ruby/schema/tabs.rb +2 -2
- data/lib/ratatui_ruby/schema/text.rb +34 -2
- data/lib/ratatui_ruby/scrollbar_state.rb +10 -2
- data/lib/ratatui_ruby/style/style.rb +18 -2
- data/lib/ratatui_ruby/style.rb +2 -2
- data/lib/ratatui_ruby/synthetic_events.rb +86 -0
- data/lib/ratatui_ruby/table_state.rb +10 -2
- data/lib/ratatui_ruby/terminal_lifecycle.rb +18 -3
- data/lib/ratatui_ruby/test_helper/event_injection.rb +62 -2
- data/lib/ratatui_ruby/test_helper/snapshot.rb +74 -9
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +98 -2
- data/lib/ratatui_ruby/test_helper/terminal.rb +50 -2
- data/lib/ratatui_ruby/test_helper/test_doubles.rb +18 -2
- data/lib/ratatui_ruby/test_helper.rb +10 -2
- data/lib/ratatui_ruby/tui/buffer_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/canvas_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/core.rb +2 -2
- data/lib/ratatui_ruby/tui/layout_factories.rb +32 -2
- data/lib/ratatui_ruby/tui/state_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/style_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/text_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/widget_factories.rb +2 -2
- data/lib/ratatui_ruby/tui.rb +11 -3
- data/lib/ratatui_ruby/version.rb +3 -3
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -2
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -2
- data/lib/ratatui_ruby/widgets/bar_chart.rb +58 -2
- data/lib/ratatui_ruby/widgets/block.rb +37 -15
- data/lib/ratatui_ruby/widgets/calendar.rb +2 -2
- data/lib/ratatui_ruby/widgets/canvas.rb +10 -2
- data/lib/ratatui_ruby/widgets/cell.rb +10 -2
- data/lib/ratatui_ruby/widgets/center.rb +10 -2
- data/lib/ratatui_ruby/widgets/chart.rb +2 -28
- data/lib/ratatui_ruby/widgets/clear.rb +10 -2
- data/lib/ratatui_ruby/widgets/cursor.rb +10 -2
- data/lib/ratatui_ruby/widgets/gauge.rb +16 -2
- data/lib/ratatui_ruby/widgets/line_gauge.rb +16 -2
- data/lib/ratatui_ruby/widgets/list.rb +41 -2
- data/lib/ratatui_ruby/widgets/list_item.rb +10 -2
- data/lib/ratatui_ruby/widgets/overlay.rb +10 -2
- data/lib/ratatui_ruby/widgets/paragraph.rb +10 -2
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -2
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -2
- data/lib/ratatui_ruby/widgets/row.rb +10 -2
- data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -2
- data/lib/ratatui_ruby/widgets/shape/label.rb +10 -2
- data/lib/ratatui_ruby/widgets/sparkline.rb +10 -2
- data/lib/ratatui_ruby/widgets/table.rb +62 -2
- data/lib/ratatui_ruby/widgets/tabs.rb +2 -2
- data/lib/ratatui_ruby/widgets.rb +2 -2
- data/lib/ratatui_ruby.rb +101 -9
- data/sig/examples/app_all_events/view.rbs +7 -1
- data/sig/examples/app_all_events/view_state.rbs +7 -1
- data/sig/examples/app_color_picker/app.rbs +5 -0
- data/sig/examples/app_stateful_interaction/app.rbs +7 -1
- data/sig/examples/verify_quickstart_dsl/app.rbs +7 -1
- data/sig/examples/verify_quickstart_lifecycle/app.rbs +7 -1
- data/sig/examples/verify_readme_usage/app.rbs +7 -1
- data/sig/examples/widget_block_demo/app.rbs +6 -0
- data/sig/examples/widget_box_demo/app.rbs +7 -1
- data/sig/examples/widget_calendar_demo/app.rbs +7 -1
- data/sig/examples/widget_cell_demo/app.rbs +7 -1
- data/sig/examples/widget_chart_demo/app.rbs +7 -1
- data/sig/examples/widget_gauge_demo/app.rbs +7 -1
- data/sig/examples/widget_layout_split/app.rbs +7 -1
- data/sig/examples/widget_line_gauge_demo/app.rbs +7 -1
- data/sig/examples/widget_list_demo/app.rbs +5 -0
- data/sig/examples/widget_map_demo/app.rbs +7 -1
- data/sig/examples/widget_popup_demo/app.rbs +7 -1
- data/sig/examples/widget_ratatui_logo_demo/app.rbs +7 -1
- data/sig/examples/widget_ratatui_mascot_demo/app.rbs +7 -1
- data/sig/examples/widget_rect/app.rbs +7 -1
- data/sig/examples/widget_render/app.rbs +7 -1
- data/sig/examples/widget_rich_text/app.rbs +7 -1
- data/sig/examples/widget_scroll_text/app.rbs +7 -1
- data/sig/examples/widget_scrollbar_demo/app.rbs +7 -1
- data/sig/examples/widget_sparkline_demo/app.rbs +7 -1
- data/sig/examples/widget_style_colors/app.rbs +7 -1
- data/sig/examples/widget_table_demo/app.rbs +7 -1
- data/sig/examples/widget_text_width/app.rbs +7 -1
- data/sig/ratatui_ruby/event.rbs +7 -1
- data/sig/ratatui_ruby/frame.rbs +15 -3
- data/sig/ratatui_ruby/list_state.rbs +11 -1
- data/sig/ratatui_ruby/ratatui_ruby.rbs +8 -2
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +7 -1
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +6 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +6 -0
- data/sig/ratatui_ruby/schema/block.rbs +7 -1
- data/sig/ratatui_ruby/schema/calendar.rbs +6 -0
- data/sig/ratatui_ruby/schema/canvas.rbs +6 -0
- data/sig/ratatui_ruby/schema/center.rbs +6 -0
- data/sig/ratatui_ruby/schema/chart.rbs +6 -9
- data/sig/ratatui_ruby/schema/constraint.rbs +14 -0
- data/sig/ratatui_ruby/schema/cursor.rbs +6 -0
- data/sig/ratatui_ruby/schema/draw.rbs +6 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +9 -1
- data/sig/ratatui_ruby/schema/layout.rbs +6 -0
- data/sig/ratatui_ruby/schema/line_gauge.rbs +9 -1
- data/sig/ratatui_ruby/schema/list.rbs +9 -1
- data/sig/ratatui_ruby/schema/list_item.rbs +7 -1
- data/sig/ratatui_ruby/schema/overlay.rbs +6 -0
- data/sig/ratatui_ruby/schema/paragraph.rbs +6 -0
- data/sig/ratatui_ruby/schema/ratatui_logo.rbs +6 -0
- data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +5 -0
- data/sig/ratatui_ruby/schema/rect.rbs +30 -0
- data/sig/ratatui_ruby/schema/row.rbs +7 -1
- data/sig/ratatui_ruby/schema/scrollbar.rbs +6 -0
- data/sig/ratatui_ruby/schema/sparkline.rbs +6 -0
- data/sig/ratatui_ruby/schema/style.rbs +7 -1
- data/sig/ratatui_ruby/schema/table.rbs +11 -1
- data/sig/ratatui_ruby/schema/tabs.rbs +6 -0
- data/sig/ratatui_ruby/schema/text.rbs +7 -1
- data/sig/ratatui_ruby/scrollbar_state.rbs +7 -1
- data/sig/ratatui_ruby/session.rbs +7 -1
- data/sig/ratatui_ruby/table_state.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/terminal.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -1
- data/sig/ratatui_ruby/test_helper.rbs +7 -1
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/core.rbs +7 -1
- data/sig/ratatui_ruby/tui/layout_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/state_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/style_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/text_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/widget_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui.rbs +7 -1
- data/sig/ratatui_ruby/version.rbs +6 -0
- data/tasks/autodoc/examples.rb +1 -1
- data/tasks/autodoc/member.rb +1 -1
- data/tasks/autodoc/name.rb +1 -1
- data/tasks/bump/cargo_lockfile.rb +1 -1
- data/tasks/bump/changelog.rb +1 -1
- data/tasks/bump/header.rb +1 -1
- data/tasks/bump/history.rb +1 -1
- data/tasks/bump/links.rb +1 -1
- data/tasks/bump/manifest.rb +1 -1
- data/tasks/bump/ruby_gem.rb +1 -1
- data/tasks/bump/sem_ver.rb +1 -1
- data/tasks/bump/unreleased_section.rb +1 -1
- data/tasks/license/headers_md.rb +223 -0
- data/tasks/license/headers_rb.rb +210 -0
- data/tasks/license/license_utils.rb +130 -0
- data/tasks/license/snippets_md.rb +315 -0
- data/tasks/license/snippets_rdoc.rb +150 -0
- data/tasks/license.rake +91 -0
- data/tasks/rdoc_config.rb +1 -1
- data/tasks/resources/build.yml.erb +13 -7
- data/tasks/sourcehut.rake +3 -1
- data/tasks/terminal_preview/app_screenshot.rb +1 -1
- data/tasks/terminal_preview/crash_report.rb +1 -1
- data/tasks/terminal_preview/example_app.rb +1 -1
- data/tasks/terminal_preview/launcher_script.rb +1 -1
- data/tasks/terminal_preview/preview_collection.rb +1 -1
- data/tasks/terminal_preview/preview_timing.rb +1 -1
- data/tasks/terminal_preview/safety_confirmation.rb +1 -1
- data/tasks/terminal_preview/saved_screenshot.rb +1 -1
- data/tasks/terminal_preview/system_appearance.rb +1 -1
- data/tasks/terminal_preview/terminal_window.rb +1 -1
- data/tasks/terminal_preview/window_id.rb +1 -1
- data/tasks/website/index_page.rb +1 -1
- data/tasks/website/version.rb +1 -1
- data/tasks/website/version_menu.rb +1 -1
- data/tasks/website/versioned_documentation.rb +1 -1
- data/tasks/website/website.rb +1 -1
- metadata +15 -3
- data/doc/migration/v0_7_0.md +0 -236
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SPDX-FileCopyrightText:
|
|
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,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SPDX-FileCopyrightText:
|
|
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,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SPDX-FileCopyrightText:
|
|
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
|
# Login Form Example
|
|
@@ -36,9 +36,15 @@ This example solves this by using the `Overlay` widget to stack a centered popup
|
|
|
36
36
|
|
|
37
37
|
## Usage
|
|
38
38
|
|
|
39
|
+
<!-- SPDX-SnippetBegin -->
|
|
40
|
+
<!--
|
|
41
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
42
|
+
SPDX-License-Identifier: MIT-0
|
|
43
|
+
-->
|
|
39
44
|
```bash
|
|
40
45
|
ruby examples/app_login_form/app.rb
|
|
41
46
|
```
|
|
47
|
+
<!-- SPDX-SnippetEnd -->
|
|
42
48
|
|
|
43
49
|
## Learning Outcomes
|
|
44
50
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
#--
|
|
4
|
-
# SPDX-FileCopyrightText:
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
5
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
6
|
#++
|
|
7
7
|
|
|
@@ -106,7 +106,7 @@ class AppStatefulInteraction
|
|
|
106
106
|
render_table(frame, table_area)
|
|
107
107
|
|
|
108
108
|
# 4. Render Help
|
|
109
|
-
help_text = "q: Quit | Tab/Arrows: Nav | Mouse: Click rows
|
|
109
|
+
help_text = "q: Quit | Tab/Arrows: Nav | Home/End: Jump | Mouse: Click rows"
|
|
110
110
|
frame.render_widget(@tui.paragraph(text: help_text), help_area)
|
|
111
111
|
end
|
|
112
112
|
end
|
|
@@ -193,10 +193,16 @@ class AppStatefulInteraction
|
|
|
193
193
|
@active_pane = (@active_pane == :list) ? :table : :list
|
|
194
194
|
|
|
195
195
|
in { type: :key, code: "down" }
|
|
196
|
-
|
|
196
|
+
move_selection_next
|
|
197
197
|
|
|
198
198
|
in { type: :key, code: "up" }
|
|
199
|
-
|
|
199
|
+
move_selection_previous
|
|
200
|
+
|
|
201
|
+
in { type: :key, code: "home" }
|
|
202
|
+
move_selection_first
|
|
203
|
+
|
|
204
|
+
in { type: :key, code: "end" }
|
|
205
|
+
move_selection_last
|
|
200
206
|
|
|
201
207
|
# Mouse Interaction
|
|
202
208
|
in { type: :mouse, kind: "down", x:, y: }
|
|
@@ -207,24 +213,72 @@ class AppStatefulInteraction
|
|
|
207
213
|
end
|
|
208
214
|
end
|
|
209
215
|
|
|
210
|
-
private def
|
|
216
|
+
private def move_selection_next
|
|
211
217
|
if @active_pane == :list
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
@table_state.select_column(nil) # Ensure clean slate
|
|
219
|
-
end
|
|
218
|
+
current = @list_state.selected || 0
|
|
219
|
+
max_index = @tables.size - 1
|
|
220
|
+
return if current >= max_index # Already at end
|
|
221
|
+
|
|
222
|
+
@list_state.select_next
|
|
223
|
+
reset_table_selection
|
|
220
224
|
else
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
+
current = @table_state.selected || 0
|
|
226
|
+
max_index = current_table_rows.size - 1
|
|
227
|
+
return if current >= max_index
|
|
228
|
+
|
|
229
|
+
@table_state.select_next
|
|
225
230
|
end
|
|
226
231
|
end
|
|
227
232
|
|
|
233
|
+
private def move_selection_previous
|
|
234
|
+
if @active_pane == :list
|
|
235
|
+
current = @list_state.selected || 0
|
|
236
|
+
return if current <= 0 # Already at start
|
|
237
|
+
|
|
238
|
+
@list_state.select_previous
|
|
239
|
+
reset_table_selection
|
|
240
|
+
else
|
|
241
|
+
current = @table_state.selected || 0
|
|
242
|
+
return if current <= 0
|
|
243
|
+
|
|
244
|
+
@table_state.select_previous
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
private def move_selection_first
|
|
249
|
+
if @active_pane == :list
|
|
250
|
+
current = @list_state.selected || 0
|
|
251
|
+
return if current == 0 # Already at first
|
|
252
|
+
|
|
253
|
+
@list_state.select_first
|
|
254
|
+
reset_table_selection
|
|
255
|
+
else
|
|
256
|
+
@table_state.select_first
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
private def move_selection_last
|
|
261
|
+
if @active_pane == :list
|
|
262
|
+
current = @list_state.selected || 0
|
|
263
|
+
max_index = @tables.size - 1
|
|
264
|
+
return if current == max_index # Already at last
|
|
265
|
+
|
|
266
|
+
@list_state.select(max_index)
|
|
267
|
+
reset_table_selection
|
|
268
|
+
else
|
|
269
|
+
@table_state.select(current_table_rows.size - 1)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
private def reset_table_selection
|
|
274
|
+
@table_state.select(0)
|
|
275
|
+
@table_state.select_column(nil)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
private def current_table_rows
|
|
279
|
+
@data[@tables[@list_state.selected || 0]]
|
|
280
|
+
end
|
|
281
|
+
|
|
228
282
|
private def handle_click(x, y)
|
|
229
283
|
if @list_area.contains?(x, y)
|
|
230
284
|
handle_list_click(y)
|
data/examples/timeout_demo.rb
CHANGED
|
@@ -11,6 +11,11 @@ This example exists as a documentation regression test. It ensures the recommend
|
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
|
+
<!-- SPDX-SnippetBegin -->
|
|
15
|
+
<!--
|
|
16
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
17
|
+
SPDX-License-Identifier: MIT-0
|
|
18
|
+
-->
|
|
14
19
|
<!-- SYNC:START:app.rb:main -->
|
|
15
20
|
```ruby
|
|
16
21
|
# 1. Initialize the terminal, start the run loop, and ensure the terminal is restored.
|
|
@@ -45,5 +50,6 @@ RatatuiRuby.run do |tui|
|
|
|
45
50
|
end
|
|
46
51
|
```
|
|
47
52
|
<!-- SYNC:END -->
|
|
53
|
+
<!-- SPDX-SnippetEnd -->
|
|
48
54
|
|
|
49
55
|
[](../../doc/getting_started/quickstart.md#simplified-api)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
#--
|
|
4
|
-
# SPDX-FileCopyrightText:
|
|
5
|
-
# SPDX-License-Identifier:
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: MIT-0
|
|
6
6
|
#++
|
|
7
7
|
|
|
8
8
|
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
@@ -23,7 +23,7 @@ class VerifyQuickstartDsl
|
|
|
23
23
|
title: "My Ruby TUI App",
|
|
24
24
|
title_alignment: :center,
|
|
25
25
|
borders: [:all],
|
|
26
|
-
|
|
26
|
+
border_style: { fg: "cyan" },
|
|
27
27
|
style: { fg: "white" }
|
|
28
28
|
)
|
|
29
29
|
)
|
|
@@ -11,6 +11,11 @@ This example exists as a documentation regression test. It ensures the layout an
|
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
|
+
<!-- SPDX-SnippetBegin -->
|
|
15
|
+
<!--
|
|
16
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
17
|
+
SPDX-License-Identifier: MIT-0
|
|
18
|
+
-->
|
|
14
19
|
<!-- SYNC:START:app.rb:main -->
|
|
15
20
|
```ruby
|
|
16
21
|
loop do
|
|
@@ -67,5 +72,6 @@ loop do
|
|
|
67
72
|
end
|
|
68
73
|
```
|
|
69
74
|
<!-- SYNC:END -->
|
|
75
|
+
<!-- SPDX-SnippetEnd -->
|
|
70
76
|
|
|
71
77
|
[](../../doc/getting_started/quickstart.md#adding-layouts)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
#--
|
|
4
|
-
# SPDX-FileCopyrightText:
|
|
5
|
-
# SPDX-License-Identifier:
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: MIT-0
|
|
6
6
|
#++
|
|
7
7
|
|
|
8
8
|
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
@@ -30,7 +30,7 @@ class VerifyQuickstartLayout
|
|
|
30
30
|
tui.paragraph(
|
|
31
31
|
text: "Hello, Ratatui!",
|
|
32
32
|
alignment: :center,
|
|
33
|
-
block: tui.block(title: "Content", borders: [:all],
|
|
33
|
+
block: tui.block(title: "Content", borders: [:all], border_style: { fg: "cyan" })
|
|
34
34
|
),
|
|
35
35
|
top
|
|
36
36
|
)
|
|
@@ -11,6 +11,11 @@ This example exists as a documentation regression test. It ensures the core life
|
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
|
+
<!-- SPDX-SnippetBegin -->
|
|
15
|
+
<!--
|
|
16
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
17
|
+
SPDX-License-Identifier: MIT-0
|
|
18
|
+
-->
|
|
14
19
|
<!-- SYNC:START:app.rb:main -->
|
|
15
20
|
```ruby
|
|
16
21
|
# 1. Initialize the terminal
|
|
@@ -58,5 +63,6 @@ ensure
|
|
|
58
63
|
end
|
|
59
64
|
```
|
|
60
65
|
<!-- SYNC:END -->
|
|
66
|
+
<!-- SPDX-SnippetEnd -->
|
|
61
67
|
|
|
62
68
|
[](../../doc/getting_started/quickstart.md#basic-application)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
#--
|
|
4
|
-
# SPDX-FileCopyrightText:
|
|
5
|
-
# SPDX-License-Identifier:
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: MIT-0
|
|
6
6
|
#++
|
|
7
7
|
|
|
8
8
|
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
@@ -27,7 +27,7 @@ class VerifyQuickstartLifecycle
|
|
|
27
27
|
title: "My Ruby TUI App",
|
|
28
28
|
title_alignment: :center,
|
|
29
29
|
borders: [:all],
|
|
30
|
-
|
|
30
|
+
border_style: { fg: "cyan" },
|
|
31
31
|
style: { fg: "white" }
|
|
32
32
|
)
|
|
33
33
|
)
|
|
@@ -11,6 +11,11 @@ This example exists as a documentation regression test. It ensures that the very
|
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
|
+
<!-- SPDX-SnippetBegin -->
|
|
15
|
+
<!--
|
|
16
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
17
|
+
SPDX-License-Identifier: MIT-0
|
|
18
|
+
-->
|
|
14
19
|
<!-- SYNC:START:app.rb:main -->
|
|
15
20
|
```ruby
|
|
16
21
|
RatatuiRuby.run do |tui|
|
|
@@ -39,5 +44,6 @@ RatatuiRuby.run do |tui|
|
|
|
39
44
|
end
|
|
40
45
|
```
|
|
41
46
|
<!-- SYNC:END -->
|
|
47
|
+
<!-- SPDX-SnippetEnd -->
|
|
42
48
|
|
|
43
49
|
[](../../README.md#usage)
|