ratatui_ruby 0.5.0 → 0.7.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.
- checksums.yaml +4 -4
- data/.builds/ruby-3.2.yml +1 -1
- data/.builds/ruby-3.3.yml +1 -1
- data/.builds/ruby-3.4.yml +1 -1
- data/.builds/ruby-4.0.0.yml +1 -1
- data/AGENTS.md +10 -4
- data/CHANGELOG.md +79 -7
- data/README.md +37 -5
- data/REUSE.toml +2 -7
- data/doc/application_architecture.md +96 -22
- data/doc/application_testing.md +76 -30
- data/doc/contributors/architectural_overhaul/chat_conversations.md +4952 -0
- data/doc/contributors/architectural_overhaul/implementation_plan.md +60 -0
- data/doc/contributors/architectural_overhaul/task.md +37 -0
- data/doc/contributors/design/ruby_frontend.md +288 -56
- data/doc/contributors/design/rust_backend.md +349 -54
- data/doc/contributors/developing_examples.md +134 -49
- data/doc/contributors/index.md +7 -5
- data/doc/contributors/v1.0.0_blockers.md +1729 -0
- data/doc/event_handling.md +11 -3
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_login_form.png +0 -0
- data/doc/images/app_stateful_interaction.png +0 -0
- data/doc/images/verify_quickstart_dsl.png +0 -0
- data/doc/images/verify_quickstart_layout.png +0 -0
- data/doc/images/verify_quickstart_lifecycle.png +0 -0
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_barchart_demo.png +0 -0
- data/doc/images/widget_block_demo.png +0 -0
- data/doc/images/widget_canvas_demo.png +0 -0
- data/doc/images/widget_cell_demo.png +0 -0
- data/doc/images/widget_center_demo.png +0 -0
- data/doc/images/widget_chart_demo.png +0 -0
- data/doc/images/widget_list_demo.png +0 -0
- data/doc/images/widget_overlay_demo.png +0 -0
- data/doc/images/widget_render.png +0 -0
- data/doc/images/widget_rich_text.png +0 -0
- data/doc/images/widget_scroll_text.png +0 -0
- data/doc/images/widget_sparkline_demo.png +0 -0
- data/doc/images/widget_table_demo.png +0 -0
- data/doc/images/widget_tabs_demo.png +0 -0
- data/doc/images/widget_text_width.png +0 -0
- data/doc/index.md +11 -6
- data/doc/interactive_design.md +2 -2
- data/doc/quickstart.md +127 -165
- data/doc/terminal_limitations.md +92 -0
- data/doc/v0.7.0_migration.md +236 -0
- data/doc/why.md +93 -0
- data/examples/app_all_events/README.md +47 -27
- data/examples/app_all_events/app.rb +38 -35
- data/examples/app_all_events/model/app_model.rb +157 -0
- data/examples/app_all_events/model/event_entry.rb +17 -0
- data/examples/app_all_events/model/msg.rb +37 -0
- data/examples/app_all_events/update.rb +73 -0
- data/examples/app_all_events/view/app_view.rb +9 -9
- data/examples/app_all_events/view/controls_view.rb +9 -7
- data/examples/app_all_events/view/counts_view.rb +13 -9
- data/examples/app_all_events/view/live_view.rb +9 -8
- data/examples/app_all_events/view/log_view.rb +11 -16
- data/examples/app_color_picker/README.md +84 -42
- data/examples/app_color_picker/app.rb +24 -62
- data/examples/app_color_picker/controls.rb +90 -0
- data/examples/app_color_picker/copy_dialog.rb +45 -49
- data/examples/app_color_picker/export_pane.rb +126 -0
- data/examples/app_color_picker/input.rb +99 -67
- data/examples/app_color_picker/main_container.rb +178 -0
- data/examples/app_color_picker/palette.rb +55 -26
- data/examples/app_login_form/README.md +49 -0
- data/examples/app_login_form/app.rb +2 -3
- data/examples/app_stateful_interaction/README.md +33 -0
- data/examples/app_stateful_interaction/app.rb +272 -0
- data/examples/timeout_demo.rb +43 -0
- data/examples/verify_quickstart_dsl/README.md +49 -0
- data/examples/verify_quickstart_dsl/app.rb +2 -0
- data/examples/verify_quickstart_layout/README.md +71 -0
- data/examples/verify_quickstart_layout/app.rb +2 -0
- data/examples/verify_quickstart_lifecycle/README.md +56 -0
- data/examples/verify_quickstart_lifecycle/app.rb +10 -4
- data/examples/verify_readme_usage/README.md +43 -0
- data/examples/verify_readme_usage/app.rb +8 -2
- data/examples/widget_barchart_demo/README.md +50 -0
- data/examples/widget_barchart_demo/app.rb +5 -5
- data/examples/widget_block_demo/README.md +36 -0
- data/examples/widget_block_demo/app.rb +256 -0
- data/examples/widget_box_demo/README.md +45 -0
- data/examples/widget_calendar_demo/README.md +39 -0
- data/examples/widget_calendar_demo/app.rb +5 -1
- data/examples/widget_canvas_demo/README.md +27 -0
- data/examples/widget_canvas_demo/app.rb +123 -0
- data/examples/widget_cell_demo/README.md +36 -0
- data/examples/widget_cell_demo/app.rb +31 -24
- data/examples/widget_center_demo/README.md +29 -0
- data/examples/widget_center_demo/app.rb +116 -0
- data/examples/widget_chart_demo/README.md +41 -0
- data/examples/widget_chart_demo/app.rb +7 -2
- data/examples/widget_gauge_demo/README.md +41 -0
- data/examples/widget_layout_split/README.md +44 -0
- data/examples/widget_line_gauge_demo/README.md +41 -0
- data/examples/widget_list_demo/README.md +49 -0
- data/examples/widget_list_demo/app.rb +91 -107
- data/examples/widget_map_demo/README.md +39 -0
- data/examples/{app_map_demo → widget_map_demo}/app.rb +4 -4
- data/examples/widget_overlay_demo/README.md +36 -0
- data/examples/widget_overlay_demo/app.rb +248 -0
- data/examples/widget_popup_demo/README.md +36 -0
- data/examples/widget_ratatui_logo_demo/README.md +34 -0
- data/examples/widget_ratatui_logo_demo/app.rb +1 -1
- data/examples/widget_ratatui_mascot_demo/README.md +34 -0
- data/examples/widget_rect/README.md +38 -0
- data/examples/widget_render/README.md +37 -0
- data/examples/widget_render/app.rb +3 -3
- data/examples/widget_rich_text/README.md +35 -0
- data/examples/widget_rich_text/app.rb +62 -33
- data/examples/widget_scroll_text/README.md +37 -0
- data/examples/widget_scroll_text/app.rb +0 -1
- data/examples/widget_scrollbar_demo/README.md +37 -0
- data/examples/widget_sparkline_demo/README.md +42 -0
- data/examples/widget_sparkline_demo/app.rb +4 -3
- data/examples/widget_style_colors/README.md +34 -0
- data/examples/widget_table_demo/README.md +48 -0
- data/examples/{app_table_select → widget_table_demo}/app.rb +65 -12
- data/examples/widget_tabs_demo/README.md +41 -0
- data/examples/widget_tabs_demo/app.rb +15 -1
- data/examples/widget_text_width/README.md +35 -0
- data/examples/widget_text_width/app.rb +113 -0
- data/exe/.gitkeep +0 -0
- data/ext/ratatui_ruby/Cargo.lock +11 -4
- data/ext/ratatui_ruby/Cargo.toml +2 -1
- data/ext/ratatui_ruby/src/events.rs +238 -26
- data/ext/ratatui_ruby/src/frame.rs +116 -3
- data/ext/ratatui_ruby/src/lib.rs +37 -6
- data/ext/ratatui_ruby/src/rendering.rs +22 -21
- data/ext/ratatui_ruby/src/string_width.rs +101 -0
- data/ext/ratatui_ruby/src/terminal.rs +39 -15
- data/ext/ratatui_ruby/src/text.rs +13 -4
- data/ext/ratatui_ruby/src/widgets/barchart.rs +24 -6
- data/ext/ratatui_ruby/src/widgets/canvas.rs +5 -5
- data/ext/ratatui_ruby/src/widgets/gauge.rs +9 -2
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +9 -2
- data/ext/ratatui_ruby/src/widgets/list.rs +179 -3
- data/ext/ratatui_ruby/src/widgets/list_state.rs +137 -0
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +93 -1
- data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
- data/ext/ratatui_ruby/src/widgets/table.rs +191 -34
- data/ext/ratatui_ruby/src/widgets/table_state.rs +121 -0
- data/lib/ratatui_ruby/buffer/cell.rb +168 -0
- data/lib/ratatui_ruby/buffer.rb +15 -0
- data/lib/ratatui_ruby/cell.rb +4 -4
- data/lib/ratatui_ruby/event/key/character.rb +35 -0
- data/lib/ratatui_ruby/event/key/media.rb +44 -0
- data/lib/ratatui_ruby/event/key/modifier.rb +95 -0
- data/lib/ratatui_ruby/event/key/navigation.rb +55 -0
- data/lib/ratatui_ruby/event/key/system.rb +45 -0
- data/lib/ratatui_ruby/event/key.rb +111 -51
- data/lib/ratatui_ruby/event/mouse.rb +3 -3
- data/lib/ratatui_ruby/event/paste.rb +1 -1
- data/lib/ratatui_ruby/frame.rb +100 -4
- data/lib/ratatui_ruby/layout/constraint.rb +95 -0
- data/lib/ratatui_ruby/layout/layout.rb +106 -0
- data/lib/ratatui_ruby/layout/rect.rb +118 -0
- data/lib/ratatui_ruby/layout.rb +19 -0
- data/lib/ratatui_ruby/list_state.rb +88 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -2
- data/lib/ratatui_ruby/schema/cursor.rb +5 -0
- data/lib/ratatui_ruby/schema/gauge.rb +3 -1
- data/lib/ratatui_ruby/schema/layout.rb +1 -1
- data/lib/ratatui_ruby/schema/line_gauge.rb +2 -2
- data/lib/ratatui_ruby/schema/list.rb +25 -4
- data/lib/ratatui_ruby/schema/list_item.rb +41 -0
- data/lib/ratatui_ruby/schema/rect.rb +43 -0
- data/lib/ratatui_ruby/schema/row.rb +66 -0
- data/lib/ratatui_ruby/schema/style.rb +24 -4
- data/lib/ratatui_ruby/schema/table.rb +29 -11
- data/lib/ratatui_ruby/schema/text.rb +96 -3
- data/lib/ratatui_ruby/scrollbar_state.rb +112 -0
- data/lib/ratatui_ruby/style/style.rb +81 -0
- data/lib/ratatui_ruby/style.rb +15 -0
- data/lib/ratatui_ruby/table_state.rb +90 -0
- data/lib/ratatui_ruby/test_helper/event_injection.rb +169 -0
- data/lib/ratatui_ruby/test_helper/snapshot.rb +414 -0
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +351 -0
- data/lib/ratatui_ruby/test_helper/terminal.rb +127 -0
- data/lib/ratatui_ruby/test_helper/test_doubles.rb +68 -0
- data/lib/ratatui_ruby/test_helper.rb +65 -358
- data/lib/ratatui_ruby/tui/buffer_factories.rb +20 -0
- data/lib/ratatui_ruby/tui/canvas_factories.rb +44 -0
- data/lib/ratatui_ruby/tui/core.rb +38 -0
- data/lib/ratatui_ruby/tui/layout_factories.rb +74 -0
- data/lib/ratatui_ruby/tui/state_factories.rb +33 -0
- data/lib/ratatui_ruby/tui/style_factories.rb +20 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +44 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +195 -0
- data/lib/ratatui_ruby/tui.rb +75 -0
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +47 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +25 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +239 -0
- data/lib/ratatui_ruby/widgets/block.rb +192 -0
- data/lib/ratatui_ruby/widgets/calendar.rb +84 -0
- data/lib/ratatui_ruby/widgets/canvas.rb +231 -0
- data/lib/ratatui_ruby/widgets/cell.rb +47 -0
- data/lib/ratatui_ruby/widgets/center.rb +59 -0
- data/lib/ratatui_ruby/widgets/chart.rb +185 -0
- data/lib/ratatui_ruby/widgets/clear.rb +54 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +42 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +72 -0
- data/lib/ratatui_ruby/widgets/line_gauge.rb +80 -0
- data/lib/ratatui_ruby/widgets/list.rb +127 -0
- data/lib/ratatui_ruby/widgets/list_item.rb +43 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +43 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +99 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +31 -0
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +36 -0
- data/lib/ratatui_ruby/widgets/row.rb +68 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +143 -0
- data/lib/ratatui_ruby/widgets/shape/label.rb +68 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +134 -0
- data/lib/ratatui_ruby/widgets/table.rb +141 -0
- data/lib/ratatui_ruby/widgets/tabs.rb +85 -0
- data/lib/ratatui_ruby/widgets.rb +40 -0
- data/lib/ratatui_ruby.rb +64 -57
- data/sig/examples/app_all_events/view.rbs +1 -1
- data/sig/examples/app_all_events/view_state.rbs +1 -1
- data/sig/examples/app_stateful_interaction/app.rbs +33 -0
- data/sig/examples/widget_block_demo/app.rbs +32 -0
- data/sig/examples/{app_map_demo → widget_map_demo}/app.rbs +2 -2
- data/sig/examples/{app_table_select → widget_table_demo}/app.rbs +2 -2
- data/sig/examples/{widget_table_flex → widget_text_width}/app.rbs +2 -3
- data/sig/ratatui_ruby/event.rbs +11 -1
- data/sig/ratatui_ruby/frame.rbs +2 -0
- data/sig/ratatui_ruby/list_state.rbs +13 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +2 -2
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +3 -3
- data/sig/ratatui_ruby/schema/gauge.rbs +2 -2
- data/sig/ratatui_ruby/schema/line_gauge.rbs +2 -2
- data/sig/ratatui_ruby/schema/list.rbs +4 -2
- data/sig/ratatui_ruby/schema/list_item.rbs +10 -0
- data/sig/ratatui_ruby/schema/rect.rbs +3 -0
- data/sig/ratatui_ruby/schema/row.rbs +22 -0
- data/sig/ratatui_ruby/schema/style.rbs +3 -3
- data/sig/ratatui_ruby/schema/table.rbs +3 -1
- data/sig/ratatui_ruby/schema/text.rbs +9 -6
- data/sig/ratatui_ruby/scrollbar_state.rbs +18 -0
- data/sig/ratatui_ruby/session.rbs +41 -48
- data/sig/ratatui_ruby/table_state.rbs +15 -0
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +16 -0
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +12 -0
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +64 -0
- data/sig/ratatui_ruby/test_helper/terminal.rbs +14 -0
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +22 -0
- data/sig/ratatui_ruby/test_helper.rbs +5 -4
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +10 -0
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +14 -0
- data/sig/ratatui_ruby/tui/core.rbs +14 -0
- data/sig/ratatui_ruby/tui/layout_factories.rbs +19 -0
- data/sig/ratatui_ruby/tui/state_factories.rbs +12 -0
- data/sig/ratatui_ruby/tui/style_factories.rbs +10 -0
- data/sig/ratatui_ruby/tui/text_factories.rbs +14 -0
- data/sig/ratatui_ruby/tui/widget_factories.rbs +39 -0
- data/sig/ratatui_ruby/tui.rbs +19 -0
- data/tasks/autodoc/examples.rb +79 -0
- data/tasks/autodoc.rake +7 -35
- data/tasks/bump/changelog.rb +3 -3
- data/tasks/bump/links.rb +67 -0
- data/tasks/sourcehut.rake +64 -21
- data/tasks/terminal_preview/app_screenshot.rb +13 -3
- data/tasks/terminal_preview/saved_screenshot.rb +4 -3
- metadata +169 -48
- data/doc/contributors/dwim_dx.md +0 -366
- data/doc/images/app_analytics.png +0 -0
- data/doc/images/app_custom_widget.png +0 -0
- data/doc/images/app_mouse_events.png +0 -0
- data/doc/images/app_table_select.png +0 -0
- data/doc/images/widget_block_padding.png +0 -0
- data/doc/images/widget_block_titles.png +0 -0
- data/doc/images/widget_list_styles.png +0 -0
- data/doc/images/widget_table_flex.png +0 -0
- data/examples/app_all_events/model/events.rb +0 -180
- data/examples/app_all_events/model/highlight.rb +0 -57
- data/examples/app_all_events/test/snapshots/after_focus_lost.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_focus_regained.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_key_a.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_mouse_click.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_multiple_events.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_paste.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_resize.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_right_click.txt +0 -24
- data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +0 -24
- data/examples/app_all_events/test/snapshots/initial_state.txt +0 -24
- data/examples/app_all_events/view_state.rb +0 -42
- data/examples/app_color_picker/scene.rb +0 -201
- data/examples/widget_block_padding/app.rb +0 -67
- data/examples/widget_block_titles/app.rb +0 -69
- data/examples/widget_list_styles/app.rb +0 -141
- data/examples/widget_table_flex/app.rb +0 -95
- data/lib/ratatui_ruby/session/autodoc.rb +0 -417
- data/lib/ratatui_ruby/session.rb +0 -163
- data/sig/examples/widget_block_padding/app.rbs +0 -11
- data/sig/examples/widget_block_titles/app.rbs +0 -11
- data/sig/examples/widget_list_styles/app.rbs +0 -11
- data/tasks/autodoc/inventory.rb +0 -61
- data/tasks/autodoc/notice.rb +0 -26
- data/tasks/autodoc/rbs.rb +0 -38
- data/tasks/autodoc/rdoc.rb +0 -45
- data/tasks/bump/comparison_links.rb +0 -41
- /data/doc/images/{app_map_demo.png → widget_map_demo.png} +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Ratatui Logo Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates branding with the official logo widget.
|
|
11
|
+
|
|
12
|
+
A polished application often needs an "About" screen or a splash screen. This widget provides the standardized project branding.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **RatatuiLogo Widget**: Renders the Ratatui ASCII art logo.
|
|
17
|
+
- **Centering**: Techniques for centering fixed-size content in a fluid layout.
|
|
18
|
+
|
|
19
|
+
## Hotkeys
|
|
20
|
+
|
|
21
|
+
- **q**: Quit
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
ruby examples/widget_ratatui_logo_demo/app.rb
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Learning Outcomes
|
|
30
|
+
|
|
31
|
+
Use this example if you need to...
|
|
32
|
+
- Create a splash screen.
|
|
33
|
+
- Add an "About" modal to your application.
|
|
34
|
+
- See how to center a widget both vertically and horizontally.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Ratatui Mascot Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates the project mascot widget for adding personality.
|
|
11
|
+
|
|
12
|
+
Interfaces can feel clinical. A friendly mascot adds charm and brand identity to your terminal application.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **RatatuiMascot Widget**: Renders the ASCII art mascot.
|
|
17
|
+
- **Block Integration**: Wrapping the mascot in a bordered block title.
|
|
18
|
+
|
|
19
|
+
## Hotkeys
|
|
20
|
+
|
|
21
|
+
- **b**: Toggle Block Border (`block`)
|
|
22
|
+
- **q**: Quit
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ruby examples/widget_ratatui_mascot_demo/app.rb
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Learning Outcomes
|
|
31
|
+
|
|
32
|
+
Use this example if you need to...
|
|
33
|
+
- Add visual flair to your UI.
|
|
34
|
+
- Create a friendly empty state or success screen.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Rect (Geometry) Widget Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates the Rect geometry primitive and hit-testing patterns.
|
|
11
|
+
|
|
12
|
+
TUI layouts are composed of rectangles. Understanding how to manipulate `Rect` objects, reuse them from the layout phase, and use them for mouse interaction is critical for building interactive apps.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **Rect Attributes**: Investigating x, y, width, and height.
|
|
17
|
+
- **Cached Layout Pattern**: Computing constraints in the render loop and reusing the resulting `Rect`s in the event loop for logic.
|
|
18
|
+
- **Hit Testing**: Using `Rect#contains?(x, y)` to determine if a mouse click happened inside a specific panel.
|
|
19
|
+
|
|
20
|
+
## Hotkeys
|
|
21
|
+
|
|
22
|
+
- **Arrows (←/→)**: Expand/Shrink Sidebar Width (Layout Constraint)
|
|
23
|
+
- **Arrows (↑/↓)**: Navigate Menu Selection (`selected_index`)
|
|
24
|
+
- **Mouse Click**: Click anywhere to see which Rect detects the hit (`contains?`)
|
|
25
|
+
- **q**: Quit
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ruby examples/widget_rect/app.rb
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Learning Outcomes
|
|
34
|
+
|
|
35
|
+
Use this example if you need to...
|
|
36
|
+
- Handle mouse clicks on specific buttons or areas.
|
|
37
|
+
- Create resizable panes (like a split pane in an IDE).
|
|
38
|
+
- Debug layout issues by inspecting Rect coordinates.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Render (Custom Widget) Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates how to build Custom Widgets using absolute coordinates.
|
|
11
|
+
|
|
12
|
+
Sometimes standard widgets aren't enough. You need to draw custom shapes, games, or graphs. This example shows how to implement the `render(area)` contract to draw anything you want while respecting layout boundaries.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **Custom Widget Contract**: Implementing a class with `render(area)`.
|
|
17
|
+
- **Coordinate Offsets**: Creating drawing logic that works regardless of where the widget is placed on screen (using `area.x + offset`).
|
|
18
|
+
- **Composability**: Wrapping custom widgets in standard `Block`s with borders.
|
|
19
|
+
|
|
20
|
+
## Hotkeys
|
|
21
|
+
|
|
22
|
+
- **n**: Next Widget (Diagonal -> Checkerboard -> Border)
|
|
23
|
+
- **p**: Previous Widget
|
|
24
|
+
- **q**: Quit
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
ruby examples/widget_render/app.rb
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Learning Outcomes
|
|
33
|
+
|
|
34
|
+
Use this example if you need to...
|
|
35
|
+
- Build a game (Snake, Tetris) inside the terminal.
|
|
36
|
+
- Create a specialized visualization (Network topology graph).
|
|
37
|
+
- Draw custom UI elements not provided by the library.
|
|
@@ -21,7 +21,7 @@ class DiagonalWidget
|
|
|
21
21
|
area.x + i,
|
|
22
22
|
area.y + i,
|
|
23
23
|
"\\",
|
|
24
|
-
RatatuiRuby::Style.new(fg: :red, modifiers: [:bold])
|
|
24
|
+
RatatuiRuby::Style::Style.new(fg: :red, modifiers: [:bold])
|
|
25
25
|
)
|
|
26
26
|
end
|
|
27
27
|
end
|
|
@@ -47,7 +47,7 @@ class CheckerboardWidget
|
|
|
47
47
|
area.x + col,
|
|
48
48
|
area.y + row,
|
|
49
49
|
@char,
|
|
50
|
-
RatatuiRuby::Style.new(fg: :cyan)
|
|
50
|
+
RatatuiRuby::Style::Style.new(fg: :cyan)
|
|
51
51
|
)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -63,7 +63,7 @@ end
|
|
|
63
63
|
class BorderWidget
|
|
64
64
|
def render(area)
|
|
65
65
|
result = []
|
|
66
|
-
style = RatatuiRuby::Style.new(fg: :green)
|
|
66
|
+
style = RatatuiRuby::Style::Style.new(fg: :green)
|
|
67
67
|
|
|
68
68
|
# Top and bottom
|
|
69
69
|
(0...area.width).each do |x| # rubocop:disable Lint/AmbiguousRange
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Rich Text Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates styling individual words and characters.
|
|
11
|
+
|
|
12
|
+
Standard strings are monochromatic. "Rich Text" is composed of `Lines` containing multiple `Spans`, where each Span has its own style. This allows for multi-colored, multi-styled text blocks.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **Spans**: Chunks of text with a specific style (e.g., "Bold Red Word").
|
|
17
|
+
- **Lines**: ordered collections of Spans that form a single row of text.
|
|
18
|
+
- **Paragraphs**: Rendering lines of rich text.
|
|
19
|
+
|
|
20
|
+
## Hotkeys
|
|
21
|
+
|
|
22
|
+
- **q**: Quit
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ruby examples/widget_rich_text/app.rb
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Learning Outcomes
|
|
31
|
+
|
|
32
|
+
Use this example if you need to...
|
|
33
|
+
- Highlight keywords in code (Syntax highlighting).
|
|
34
|
+
- Create status lines with icons (e.g., "✔ Success" where the checkmark is green).
|
|
35
|
+
- Emphasize specific data points in a paragraph.
|
|
@@ -12,6 +12,7 @@ require "ratatui_ruby"
|
|
|
12
12
|
class WidgetRichText
|
|
13
13
|
def initialize
|
|
14
14
|
@scroll_pos = 0
|
|
15
|
+
@color_index = 0
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def run
|
|
@@ -44,38 +45,52 @@ class WidgetRichText
|
|
|
44
45
|
private def simple_text_line_example
|
|
45
46
|
# Example 1: A line with mixed styles
|
|
46
47
|
@tui.paragraph(
|
|
47
|
-
text:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
48
|
+
text: [
|
|
49
|
+
@tui.text_line(
|
|
50
|
+
spans: [
|
|
51
|
+
@tui.text_span(
|
|
52
|
+
content: "Normal text, ",
|
|
53
|
+
style: nil
|
|
54
|
+
),
|
|
55
|
+
@tui.text_span(
|
|
56
|
+
content: "Bold Text",
|
|
57
|
+
style: @tui.style(modifiers: [:bold])
|
|
58
|
+
),
|
|
59
|
+
@tui.text_span(
|
|
60
|
+
content: ", ",
|
|
61
|
+
style: nil
|
|
62
|
+
),
|
|
63
|
+
@tui.text_span(
|
|
64
|
+
content: "Italic Text",
|
|
65
|
+
style: @tui.style(modifiers: [:italic])
|
|
66
|
+
),
|
|
67
|
+
@tui.text_span(
|
|
68
|
+
content: ", ",
|
|
69
|
+
style: nil
|
|
70
|
+
),
|
|
71
|
+
@tui.text_span(
|
|
72
|
+
content: "Red Text",
|
|
73
|
+
style: @tui.style(fg: :red)
|
|
74
|
+
),
|
|
75
|
+
@tui.text_span(
|
|
76
|
+
content: ".",
|
|
77
|
+
style: nil
|
|
78
|
+
),
|
|
79
|
+
]
|
|
80
|
+
),
|
|
81
|
+
@tui.text_line(spans: []),
|
|
82
|
+
@tui.text_line(
|
|
83
|
+
spans: [
|
|
84
|
+
@tui.text_span(content: "Integer Color Test: "),
|
|
85
|
+
@tui.text_span(content: "Color #{@color_index}", style: @tui.style(fg: @color_index)),
|
|
86
|
+
@tui.text_span(content: " (Use "),
|
|
87
|
+
@tui.text_span(content: "↑ ↓", style: @tui.style(modifiers: [:bold])),
|
|
88
|
+
@tui.text_span(content: " for +/- 1,", style: nil),
|
|
89
|
+
@tui.text_span(content: "→ ←", style: @tui.style(modifiers: [:bold])),
|
|
90
|
+
@tui.text_span(content: " for +/- 10)", style: nil),
|
|
91
|
+
]
|
|
92
|
+
),
|
|
93
|
+
],
|
|
79
94
|
block: @tui.block(
|
|
80
95
|
title: "Simple Rich Text",
|
|
81
96
|
borders: [:all]
|
|
@@ -113,7 +128,11 @@ class WidgetRichText
|
|
|
113
128
|
spans: [
|
|
114
129
|
@tui.text_span(content: "Press ", style: nil),
|
|
115
130
|
@tui.text_span(content: "Q", style: @tui.style(modifiers: [:bold])),
|
|
116
|
-
@tui.text_span(content: " to quit", style: nil),
|
|
131
|
+
@tui.text_span(content: " to quit, ", style: nil),
|
|
132
|
+
@tui.text_span(content: "↑ ↓", style: @tui.style(modifiers: [:bold])),
|
|
133
|
+
@tui.text_span(content: " to adjust color by 1, ", style: nil),
|
|
134
|
+
@tui.text_span(content: "← →", style: @tui.style(modifiers: [:bold])),
|
|
135
|
+
@tui.text_span(content: " to adjust color by 10.", style: nil),
|
|
117
136
|
]
|
|
118
137
|
),
|
|
119
138
|
],
|
|
@@ -128,6 +147,16 @@ class WidgetRichText
|
|
|
128
147
|
event = @tui.poll_event
|
|
129
148
|
return :quit if event == "q" || event == :esc || event == :ctrl_c
|
|
130
149
|
|
|
150
|
+
if event.left?
|
|
151
|
+
@color_index = (@color_index - 10) % 256
|
|
152
|
+
elsif event.right?
|
|
153
|
+
@color_index = (@color_index + 10) % 256
|
|
154
|
+
elsif event.up?
|
|
155
|
+
@color_index = (@color_index + 1) % 256
|
|
156
|
+
elsif event.down?
|
|
157
|
+
@color_index = (@color_index - 1) % 256
|
|
158
|
+
end
|
|
159
|
+
|
|
131
160
|
nil
|
|
132
161
|
end
|
|
133
162
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Scroll Text Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates scrolling long text content within a fixed viewport.
|
|
11
|
+
|
|
12
|
+
Sometimes text exceeds the available space. The `Paragraph` widget supports a `scroll` parameter to simulate a viewport, allowing users to pan vertically and horizontally.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **Vertical Scrolling**: Moving through lines of text.
|
|
17
|
+
- **Horizontal Scrolling**: Panning across long, unwrapped lines.
|
|
18
|
+
- **State Management**: tracking `scroll_x` and `scroll_y` offsets in the application state.
|
|
19
|
+
|
|
20
|
+
## Hotkeys
|
|
21
|
+
|
|
22
|
+
- **Arrows (↑/↓)**: Scroll Vertically (`scroll`)
|
|
23
|
+
- **Arrows (←/→)**: Scroll Horizontally (`scroll`)
|
|
24
|
+
- **q**: Quit
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
ruby examples/widget_scroll_text/app.rb
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Learning Outcomes
|
|
33
|
+
|
|
34
|
+
Use this example if you need to...
|
|
35
|
+
- Build a log viewer.
|
|
36
|
+
- Create a "terms and conditions" scrollbox.
|
|
37
|
+
- Display code snippets that might be wider than the terminal.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Scrollbar Widget Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates explicit scrollbars for navigation feedback.
|
|
11
|
+
|
|
12
|
+
Content overflows. Users get lost in long lists. Scrollbars provide essential spatial awareness ("How far down am I?") and navigation controls.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **Orientation**: Vertical, Horizontal, and variation modes (Right/Left, Top/Bottom).
|
|
17
|
+
- **Styling**: Custom characters for Track, Thumb, and arrows.
|
|
18
|
+
- **State Integration**: Linking the scrollbar `position` to the content view state.
|
|
19
|
+
|
|
20
|
+
## Hotkeys
|
|
21
|
+
|
|
22
|
+
- **Mouse Wheel**: Scroll content (`position`)
|
|
23
|
+
- **s**: Cycle Scrollbar Theme (Standard, Rounded, ASCII, Minimal)
|
|
24
|
+
- **o**: Cycle Orientation (`orientation`)
|
|
25
|
+
- **q**: Quit
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ruby examples/widget_scrollbar_demo/app.rb
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Learning Outcomes
|
|
34
|
+
|
|
35
|
+
Use this example if you need to...
|
|
36
|
+
- Add visual scroll indicators to Lists or Tables.
|
|
37
|
+
- Implement specialized inputs like sliders or volume controls.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Sparkline Widget Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates high-density data visualization in a condensed footprint.
|
|
11
|
+
|
|
12
|
+
Users need context. A single number ("90% CPU") tells you status, but not the trend. Full charts take up too much space. Sparklines condense history into a single line, perfect for headers and dashboards.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **High Density**: Showing dozens of data points in a small area.
|
|
17
|
+
- **Direction**: Rendering Left-to-Right (standard) or Right-to-Left (like a scrolling ticker).
|
|
18
|
+
- **Gaps**: Handling `nil` values with "absent symbols" to indicate missing data.
|
|
19
|
+
- **Styling**: Using colors and custom characters to indicate severity or type.
|
|
20
|
+
|
|
21
|
+
## Hotkeys
|
|
22
|
+
|
|
23
|
+
- **Up/Down (↑/↓)**: Cycle Data Set (`data`)
|
|
24
|
+
- **d**: Cycle Direction (`direction`)
|
|
25
|
+
- **c**: Cycle Color (`style`)
|
|
26
|
+
- **m**: Cycle Absent Value Marker Symbol (`absent_value_symbol`)
|
|
27
|
+
- **s**: Cycle Absent Value Marker Style (`absent_value_style`)
|
|
28
|
+
- **b**: Cycle Bar Character Set (`bar_set`)
|
|
29
|
+
- **q**: Quit
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
ruby examples/widget_sparkline_demo/app.rb
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Learning Outcomes
|
|
38
|
+
|
|
39
|
+
Use this example if you need to...
|
|
40
|
+
- Add a "CPU Load" graph to your header.
|
|
41
|
+
- Visualize stock price trends in a list row.
|
|
42
|
+
- Monitor memory usage over the last 60 seconds.
|
|
@@ -57,7 +57,8 @@ class WidgetSparklineDemo
|
|
|
57
57
|
data: [1, 5, 1, 8, 1, 6, 1, 9, 1, 7, 1, 10],
|
|
58
58
|
},
|
|
59
59
|
]
|
|
60
|
-
@data_index =
|
|
60
|
+
@data_index = 2
|
|
61
|
+
srand(12345) # Ensure reproducible "Random" data for snapshots
|
|
61
62
|
|
|
62
63
|
@directions = [
|
|
63
64
|
{ name: "Left to Right", direction: :left_to_right },
|
|
@@ -72,7 +73,7 @@ class WidgetSparklineDemo
|
|
|
72
73
|
{ name: "Cyan", style: @tui.style(fg: :cyan) },
|
|
73
74
|
{ name: "Magenta", style: @tui.style(fg: :magenta) },
|
|
74
75
|
]
|
|
75
|
-
@style_index =
|
|
76
|
+
@style_index = 3
|
|
76
77
|
|
|
77
78
|
@absent_symbols = [
|
|
78
79
|
{ name: "None", symbol: nil },
|
|
@@ -89,7 +90,7 @@ class WidgetSparklineDemo
|
|
|
89
90
|
{ name: "Dim Red", style: @tui.style(fg: :red, modifiers: [:dim]) },
|
|
90
91
|
{ name: "Dim Yellow", style: @tui.style(fg: :yellow, modifiers: [:dim]) },
|
|
91
92
|
]
|
|
92
|
-
@absent_style_index =
|
|
93
|
+
@absent_style_index = 2
|
|
93
94
|
|
|
94
95
|
@bar_sets = [
|
|
95
96
|
{ name: "Default (Block)", set: nil },
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Style Colors Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates high-fidelity color support.
|
|
11
|
+
|
|
12
|
+
Terminals support millions of colors. This example generates a mathematically precise HSL gradient to prove the rendering engine's color fidelity.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **HSL to RGB Conversion**: generating smooth color gradients programmatically.
|
|
17
|
+
- **TrueColor Support**: Rendering arbitrary HEX colors.
|
|
18
|
+
|
|
19
|
+
## Hotkeys
|
|
20
|
+
|
|
21
|
+
- **q** / **Ctrl+c**: Quit
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
ruby examples/widget_style_colors/app.rb
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Learning Outcomes
|
|
30
|
+
|
|
31
|
+
Use this example if you need to...
|
|
32
|
+
- Create meaningful heatmaps.
|
|
33
|
+
- Generate color palettes dynamically.
|
|
34
|
+
- Test your terminal's color support capabilities.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Table Widget Example
|
|
7
|
+
|
|
8
|
+
[](app.rb)
|
|
9
|
+
|
|
10
|
+
Demonstrates advanced options for the `Table` widget, including selection, row-level highlighting, and column-level highlighting.
|
|
11
|
+
|
|
12
|
+
Data grids are complex. Users expect to navigate them with keys, select rows, and clearly see which cell is active. The `Table` widget provides these features out of the box efficiently.
|
|
13
|
+
|
|
14
|
+
## Features Demonstrated
|
|
15
|
+
|
|
16
|
+
- **Selection State**: Managing `selected_row` and `selected_column` to track user focus.
|
|
17
|
+
- **Complex Highlighting**:
|
|
18
|
+
- **Row**: Highlight the entire active row.
|
|
19
|
+
- **Highlight Symbol:** Adding a visual indicator (like `> `) to the selected row.
|
|
20
|
+
- **Spacing:** Adjusting `column_spacing` and `highlight_spacing` to control layout density.
|
|
21
|
+
- **Flex Layout:** Switching between different column distribution modes (`legacy`, `start`, `space_between`, etc.).
|
|
22
|
+
- **Offset Control:** Manually controlling the scroll position using `offset`.
|
|
23
|
+
|
|
24
|
+
## Hotkeys
|
|
25
|
+
|
|
26
|
+
- **Arrows (↑/↓)**: Navigate Rows (`selected_row`)
|
|
27
|
+
- **Arrows (←/→)**: Navigate Columns (`selected_column`)
|
|
28
|
+
- **x**: Toggle Row Selection (`selected_row` = nil)
|
|
29
|
+
- **s**: Cycle Table Style (`style`)
|
|
30
|
+
- **p**: Cycle Spacing (`highlight_spacing`)
|
|
31
|
+
- **c**: Toggle Column Highlight (`column_highlight_style`)
|
|
32
|
+
- **z**: Toggle Cell Highlight (`cell_highlight_style`)
|
|
33
|
+
- **o**: Cycle Offset Mode (`offset`)
|
|
34
|
+
- **f**: Cycle Flex Mode (`flex`)
|
|
35
|
+
- **q**: Quit
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
ruby examples/widget_table_demo/app.rb
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Learning Outcomes
|
|
44
|
+
|
|
45
|
+
Use this example if you need to...
|
|
46
|
+
- Build a file explorer or process list.
|
|
47
|
+
- Create a data-heavy dashboard.
|
|
48
|
+
- Handle conflicting style requirements (e.g., "Highlight this row, but make this error cell red").
|