ratatui_ruby 1.1.0 → 1.1.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/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/lib/ratatui_ruby/version.rb +1 -1
- metadata +1 -255
- data/.builds/ruby-3.2.yml +0 -54
- data/.builds/ruby-3.3.yml +0 -54
- data/.builds/ruby-3.4.yml +0 -54
- data/.builds/ruby-4.0.0.yml +0 -54
- data/.pre-commit-config.yaml +0 -16
- data/.rubocop.yml +0 -10
- data/AGENTS.md +0 -147
- data/CHANGELOG.md +0 -736
- data/README.md +0 -187
- data/README.rdoc +0 -302
- data/Rakefile +0 -11
- data/Steepfile +0 -50
- data/doc/concepts/application_architecture.md +0 -321
- data/doc/concepts/application_testing.md +0 -193
- data/doc/concepts/async.md +0 -190
- data/doc/concepts/custom_widgets.md +0 -247
- data/doc/concepts/debugging.md +0 -401
- data/doc/concepts/event_handling.md +0 -162
- data/doc/concepts/interactive_design.md +0 -146
- data/doc/contributors/auditing/parity.md +0 -239
- data/doc/contributors/design/ruby_frontend.md +0 -448
- data/doc/contributors/design/rust_backend.md +0 -434
- data/doc/contributors/design.md +0 -11
- data/doc/contributors/developing_examples.md +0 -400
- data/doc/contributors/documentation_style.md +0 -121
- data/doc/contributors/index.md +0 -21
- data/doc/contributors/releasing.md +0 -215
- data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -381
- data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -200
- data/doc/contributors/todo/align/term.md +0 -351
- data/doc/contributors/todo/align/terminal.md +0 -647
- data/doc/contributors/todo/future_work.md +0 -169
- data/doc/contributors/upstream_requests/paragraph_span_rects.md +0 -259
- data/doc/contributors/upstream_requests/tab_rects.md +0 -173
- data/doc/contributors/upstream_requests/title_rects.md +0 -132
- data/doc/custom.css +0 -22
- data/doc/getting_started/quickstart.md +0 -291
- data/doc/getting_started/why.md +0 -93
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_cli_rich_moments.gif +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_debugging_showcase.gif +0 -0
- data/doc/images/app_debugging_showcase.png +0 -0
- data/doc/images/app_external_editor.gif +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.png +0 -0
- data/doc/images/widget_block.png +0 -0
- data/doc/images/widget_box.png +0 -0
- data/doc/images/widget_calendar.png +0 -0
- data/doc/images/widget_canvas.png +0 -0
- data/doc/images/widget_cell.png +0 -0
- data/doc/images/widget_center.png +0 -0
- data/doc/images/widget_chart.png +0 -0
- data/doc/images/widget_gauge.png +0 -0
- data/doc/images/widget_layout_split.png +0 -0
- data/doc/images/widget_line_gauge.png +0 -0
- data/doc/images/widget_list.png +0 -0
- data/doc/images/widget_map.png +0 -0
- data/doc/images/widget_overlay.png +0 -0
- data/doc/images/widget_popup.png +0 -0
- data/doc/images/widget_ratatui_logo.png +0 -0
- data/doc/images/widget_ratatui_mascot.png +0 -0
- data/doc/images/widget_rect.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_scrollbar.png +0 -0
- data/doc/images/widget_sparkline.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/images/widget_table.png +0 -0
- data/doc/images/widget_tabs.png +0 -0
- data/doc/images/widget_text_width.png +0 -0
- data/doc/index.md +0 -34
- data/doc/troubleshooting/async.md +0 -4
- data/doc/troubleshooting/terminal_limitations.md +0 -131
- data/doc/troubleshooting/tui_output.md +0 -197
- data/examples/app_all_events/README.md +0 -114
- data/examples/app_all_events/app.rb +0 -98
- data/examples/app_all_events/model/app_model.rb +0 -159
- data/examples/app_all_events/model/event_color_cycle.rb +0 -43
- data/examples/app_all_events/model/event_entry.rb +0 -94
- data/examples/app_all_events/model/msg.rb +0 -39
- data/examples/app_all_events/model/timestamp.rb +0 -56
- data/examples/app_all_events/update.rb +0 -75
- data/examples/app_all_events/view/app_view.rb +0 -80
- data/examples/app_all_events/view/controls_view.rb +0 -54
- data/examples/app_all_events/view/counts_view.rb +0 -61
- data/examples/app_all_events/view/live_view.rb +0 -72
- data/examples/app_all_events/view/log_view.rb +0 -57
- data/examples/app_all_events/view.rb +0 -9
- data/examples/app_cli_rich_moments/README.md +0 -81
- data/examples/app_cli_rich_moments/app.rb +0 -189
- data/examples/app_color_picker/README.md +0 -156
- data/examples/app_color_picker/app.rb +0 -76
- data/examples/app_color_picker/clipboard.rb +0 -86
- data/examples/app_color_picker/color.rb +0 -193
- data/examples/app_color_picker/controls.rb +0 -92
- data/examples/app_color_picker/copy_dialog.rb +0 -168
- data/examples/app_color_picker/export_pane.rb +0 -128
- data/examples/app_color_picker/harmony.rb +0 -58
- data/examples/app_color_picker/input.rb +0 -176
- data/examples/app_color_picker/main_container.rb +0 -180
- data/examples/app_color_picker/palette.rb +0 -111
- data/examples/app_debugging_showcase/README.md +0 -119
- data/examples/app_debugging_showcase/app.rb +0 -318
- data/examples/app_external_editor/README.md +0 -62
- data/examples/app_external_editor/app.rb +0 -344
- data/examples/app_login_form/README.md +0 -58
- data/examples/app_login_form/app.rb +0 -109
- data/examples/app_stateful_interaction/README.md +0 -35
- data/examples/app_stateful_interaction/app.rb +0 -328
- data/examples/timeout_demo.rb +0 -45
- data/examples/verify_quickstart_dsl/README.md +0 -55
- data/examples/verify_quickstart_dsl/app.rb +0 -49
- data/examples/verify_quickstart_layout/README.md +0 -77
- data/examples/verify_quickstart_layout/app.rb +0 -73
- data/examples/verify_quickstart_lifecycle/README.md +0 -68
- data/examples/verify_quickstart_lifecycle/app.rb +0 -62
- data/examples/verify_readme_usage/README.md +0 -49
- data/examples/verify_readme_usage/app.rb +0 -42
- data/examples/verify_website_managed/README.md +0 -48
- data/examples/verify_website_managed/app.rb +0 -36
- data/examples/verify_website_menu/README.md +0 -60
- data/examples/verify_website_menu/app.rb +0 -84
- data/examples/verify_website_spinner/README.md +0 -44
- data/examples/verify_website_spinner/app.rb +0 -34
- data/examples/widget_barchart/README.md +0 -58
- data/examples/widget_barchart/app.rb +0 -240
- data/examples/widget_block/README.md +0 -44
- data/examples/widget_block/app.rb +0 -258
- data/examples/widget_box/README.md +0 -54
- data/examples/widget_box/app.rb +0 -255
- data/examples/widget_calendar/README.md +0 -48
- data/examples/widget_calendar/app.rb +0 -115
- data/examples/widget_canvas/README.md +0 -31
- data/examples/widget_canvas/app.rb +0 -130
- data/examples/widget_cell/README.md +0 -45
- data/examples/widget_cell/app.rb +0 -112
- data/examples/widget_center/README.md +0 -33
- data/examples/widget_center/app.rb +0 -118
- data/examples/widget_chart/README.md +0 -50
- data/examples/widget_chart/app.rb +0 -220
- data/examples/widget_gauge/README.md +0 -50
- data/examples/widget_gauge/app.rb +0 -229
- data/examples/widget_layout_split/README.md +0 -53
- data/examples/widget_layout_split/app.rb +0 -260
- data/examples/widget_line_gauge/README.md +0 -50
- data/examples/widget_line_gauge/app.rb +0 -219
- data/examples/widget_list/README.md +0 -58
- data/examples/widget_list/app.rb +0 -382
- data/examples/widget_map/README.md +0 -48
- data/examples/widget_map/app.rb +0 -95
- data/examples/widget_overlay/README.md +0 -45
- data/examples/widget_overlay/app.rb +0 -250
- data/examples/widget_popup/README.md +0 -45
- data/examples/widget_popup/app.rb +0 -106
- data/examples/widget_ratatui_logo/README.md +0 -43
- data/examples/widget_ratatui_logo/app.rb +0 -104
- data/examples/widget_ratatui_mascot/README.md +0 -43
- data/examples/widget_ratatui_mascot/app.rb +0 -95
- data/examples/widget_rect/README.md +0 -53
- data/examples/widget_rect/app.rb +0 -222
- data/examples/widget_render/README.md +0 -46
- data/examples/widget_render/app.rb +0 -186
- data/examples/widget_render/app.rbs +0 -41
- data/examples/widget_rich_text/README.md +0 -44
- data/examples/widget_rich_text/app.rb +0 -193
- data/examples/widget_scroll_text/README.md +0 -46
- data/examples/widget_scroll_text/app.rb +0 -109
- data/examples/widget_scrollbar/README.md +0 -46
- data/examples/widget_scrollbar/app.rb +0 -155
- data/examples/widget_sparkline/README.md +0 -51
- data/examples/widget_sparkline/app.rb +0 -277
- data/examples/widget_style_colors/README.md +0 -43
- data/examples/widget_style_colors/app.rb +0 -83
- data/examples/widget_table/README.md +0 -57
- data/examples/widget_table/app.rb +0 -285
- data/examples/widget_tabs/README.md +0 -50
- data/examples/widget_tabs/app.rb +0 -183
- data/examples/widget_text_width/README.md +0 -44
- data/examples/widget_text_width/app.rb +0 -117
- data/migrate_to_buffer.rb +0 -145
- data/mise.toml +0 -8
- data/tasks/autodoc/examples.rb +0 -87
- data/tasks/autodoc/member.rb +0 -58
- data/tasks/autodoc/name.rb +0 -21
- data/tasks/autodoc.rake +0 -21
- data/tasks/bump/bump_workflow.rb +0 -49
- data/tasks/bump/cargo_lockfile.rb +0 -21
- data/tasks/bump/changelog.rb +0 -104
- data/tasks/bump/header.rb +0 -32
- data/tasks/bump/history.rb +0 -32
- data/tasks/bump/links.rb +0 -69
- data/tasks/bump/manifest.rb +0 -33
- data/tasks/bump/patch_release.rb +0 -19
- data/tasks/bump/release_branch.rb +0 -17
- data/tasks/bump/release_from_trunk.rb +0 -49
- data/tasks/bump/repository.rb +0 -54
- data/tasks/bump/ruby_gem.rb +0 -29
- data/tasks/bump/sem_ver.rb +0 -44
- data/tasks/bump/unreleased_section.rb +0 -73
- data/tasks/bump.rake +0 -61
- data/tasks/doc/documentation.rb +0 -59
- data/tasks/doc/link/file_url.rb +0 -30
- data/tasks/doc/link/relative_path.rb +0 -61
- data/tasks/doc/link/web_url.rb +0 -55
- data/tasks/doc/link.rb +0 -52
- data/tasks/doc/link_audit.rb +0 -116
- data/tasks/doc/problem.rb +0 -40
- data/tasks/doc/source_file.rb +0 -93
- data/tasks/doc.rake +0 -905
- data/tasks/example_viewer.html.erb +0 -172
- data/tasks/extension.rake +0 -14
- data/tasks/license/headers_md.rb +0 -223
- data/tasks/license/headers_rb.rb +0 -210
- data/tasks/license/license_utils.rb +0 -130
- data/tasks/license/snippets_md.rb +0 -315
- data/tasks/license/snippets_rdoc.rb +0 -150
- data/tasks/license.rake +0 -91
- data/tasks/lint.rake +0 -170
- data/tasks/rbs_predicates/predicate_catalog.rb +0 -52
- data/tasks/rbs_predicates/predicate_tests.rb +0 -124
- data/tasks/rbs_predicates/rbs_signature.rb +0 -63
- data/tasks/rbs_predicates.rake +0 -31
- data/tasks/rdoc_config.rb +0 -29
- data/tasks/resources/build.yml.erb +0 -60
- data/tasks/resources/index.html.erb +0 -141
- data/tasks/resources/rubies.yml +0 -7
- data/tasks/sourcehut.rake +0 -110
- data/tasks/steep.rake +0 -11
- data/tasks/terminal_preview/app_screenshot.rb +0 -45
- data/tasks/terminal_preview/crash_report.rb +0 -54
- data/tasks/terminal_preview/example_app.rb +0 -27
- data/tasks/terminal_preview/launcher_script.rb +0 -48
- data/tasks/terminal_preview/preview_collection.rb +0 -60
- data/tasks/terminal_preview/preview_timing.rb +0 -24
- data/tasks/terminal_preview/safety_confirmation.rb +0 -58
- data/tasks/terminal_preview/saved_screenshot.rb +0 -56
- data/tasks/terminal_preview/system_appearance.rb +0 -13
- data/tasks/terminal_preview/terminal_window.rb +0 -138
- data/tasks/terminal_preview/window_id.rb +0 -16
- data/tasks/terminal_preview.rake +0 -30
- data/tasks/test.rake +0 -36
- data/tasks/website/index_page.rb +0 -30
- data/tasks/website/version.rb +0 -122
- data/tasks/website/version_menu.rb +0 -68
- data/tasks/website/versioned_documentation.rb +0 -83
- data/tasks/website/website.rb +0 -53
- data/tasks/website.rake +0 -28
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Feature Request: Expose Block Title Rects
|
|
7
|
-
|
|
8
|
-
## Summary
|
|
9
|
-
|
|
10
|
-
`Block` computes the position of each title during rendering but does not expose this information. Interactive applications need title rects for mouse click hit-testing.
|
|
11
|
-
|
|
12
|
-
## The Problem
|
|
13
|
-
|
|
14
|
-
Building clickable TUI interfaces requires knowing where widgets render. When a block has multiple titles (e.g., a left-aligned title and a right-aligned toggle label), each title occupies a specific screen region. The application cannot query these regions.
|
|
15
|
-
|
|
16
|
-
Currently, the only options are:
|
|
17
|
-
|
|
18
|
-
1. **Recompute the layout manually.** Duplicate the logic from `render_left_titles`, `render_right_titles`, and `render_center_titles`. This is fragile—any upstream change breaks the user's code.
|
|
19
|
-
2. **Use coarse hit-testing.** Check if a click is anywhere in the block's top border row. This cannot distinguish between multiple titles.
|
|
20
|
-
|
|
21
|
-
Neither approach is satisfactory.
|
|
22
|
-
|
|
23
|
-
## Use Case
|
|
24
|
-
|
|
25
|
-
Consider a TUI with a tabbed interface where the block's title bar contains:
|
|
26
|
-
|
|
27
|
-
- A left-aligned title: `"Announce v0.7.3"`
|
|
28
|
-
- A right-aligned toggle: `"emate"` (clickable to switch email clients)
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
┌Announce v0.7.3───────────────────────────────emate┐
|
|
32
|
-
│ Preview Email ▸ Preview Commit ▸ Announce │
|
|
33
|
-
│ │
|
|
34
|
-
└───────────────────────────────────────────────────┘
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
The application wants to:
|
|
38
|
-
|
|
39
|
-
1. Detect clicks on `"emate"` and toggle the email client
|
|
40
|
-
2. Detect clicks on tab names and switch tabs
|
|
41
|
-
3. Ignore clicks on the border characters
|
|
42
|
-
|
|
43
|
-
Without title rects, the application must manually compute where `"emate"` renders based on block width, borders, alignment, and title content. This duplicates private logic from `Block::render_right_titles`.
|
|
44
|
-
|
|
45
|
-
## Current State (v0.30.0)
|
|
46
|
-
|
|
47
|
-
`Block` has private methods that compute title areas:
|
|
48
|
-
|
|
49
|
-
```rust
|
|
50
|
-
// Private - not accessible to users
|
|
51
|
-
fn titles_area(&self, area: Rect, position: Position) -> Rect { ... }
|
|
52
|
-
fn render_left_titles(&self, position: Position, area: Rect, buf: &mut Buffer) { ... }
|
|
53
|
-
fn render_center_titles(&self, position: Position, area: Rect, buf: &mut Buffer) { ... }
|
|
54
|
-
fn render_right_titles(&self, position: Position, area: Rect, buf: &mut Buffer) { ... }
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
The `titles_area` method computes the general title region. The `render_*_titles` methods compute individual title rects during rendering but do not expose them.
|
|
58
|
-
|
|
59
|
-
## Proposed API
|
|
60
|
-
|
|
61
|
-
Following the pattern established by `Block::inner(area)`, add a pure computation method that takes an area and returns computed sub-rects without rendering:
|
|
62
|
-
|
|
63
|
-
```rust
|
|
64
|
-
impl Block {
|
|
65
|
-
/// Returns the bounding rect for each title given an area.
|
|
66
|
-
///
|
|
67
|
-
/// The rects are returned in the same order as titles were added.
|
|
68
|
-
/// Useful for hit-testing mouse clicks against specific titles.
|
|
69
|
-
///
|
|
70
|
-
/// # Example
|
|
71
|
-
///
|
|
72
|
-
/// ```rust
|
|
73
|
-
/// let block = Block::bordered()
|
|
74
|
-
/// .title_top("Left Title")
|
|
75
|
-
/// .title_top(Line::from("Right").right_aligned());
|
|
76
|
-
///
|
|
77
|
-
/// let rects = block.title_rects(area);
|
|
78
|
-
/// if rects[1].contains(mouse_position) {
|
|
79
|
-
/// // Clicked on "Right"
|
|
80
|
-
/// }
|
|
81
|
-
/// ```
|
|
82
|
-
pub fn title_rects(&self, area: Rect) -> Vec<Rect> { ... }
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Alternatively, expose the individual areas by alignment:
|
|
87
|
-
|
|
88
|
-
```rust
|
|
89
|
-
/// Returns the rect for the title at the given index.
|
|
90
|
-
pub fn title_rect(&self, area: Rect, index: usize) -> Option<Rect> { ... }
|
|
91
|
-
|
|
92
|
-
/// Returns the titles area for a given position (top or bottom).
|
|
93
|
-
pub fn titles_area(&self, area: Rect, position: Position) -> Rect { ... }
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Workaround
|
|
97
|
-
|
|
98
|
-
Without this API, users must replicate the title layout algorithm. Here is the current approach used in RatatuiRuby:
|
|
99
|
-
|
|
100
|
-
```rust
|
|
101
|
-
// Manually compute right-aligned title position
|
|
102
|
-
let email_label_width = email_client.len() as u16;
|
|
103
|
-
let email_label_x = area.x + area.width - email_label_width - 2; // border + padding
|
|
104
|
-
let email_label_rect = Rect::new(email_label_x, area.y, email_label_width, 1);
|
|
105
|
-
|
|
106
|
-
if email_label_rect.contains(click_position) {
|
|
107
|
-
toggle_email_client();
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
This works for simple cases but breaks when:
|
|
112
|
-
|
|
113
|
-
- Borders are not all present (`Borders::LEFT` affects x offset)
|
|
114
|
-
- Multiple right-aligned titles exist (spacing affects position)
|
|
115
|
-
- Upstream layout logic changes
|
|
116
|
-
|
|
117
|
-
## Impact
|
|
118
|
-
|
|
119
|
-
This feature benefits any application with interactive block titles:
|
|
120
|
-
|
|
121
|
-
- Clickable tabs in title bars
|
|
122
|
-
- Toggle buttons in headers
|
|
123
|
-
- Breadcrumb navigation
|
|
124
|
-
- Window controls (minimize/maximize/close buttons in the title area)
|
|
125
|
-
|
|
126
|
-
Related discussion: [ratatui#738](https://github.com/ratatui/ratatui/issues/738) (title positioning behavior)
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
This issue includes creative contributions from Claude (Anthropic) via Antigravity (Google). [https://declare-ai.org/1.0.0/creative.html](https://declare-ai.org/1.0.0/creative.html)
|
|
131
|
-
|
|
132
|
-
*Discovered while implementing click handling for block title toggles in RatatuiRuby.*
|
data/doc/custom.css
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
img {
|
|
7
|
-
max-width: 100%;
|
|
8
|
-
height: auto;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.theme-toggle {
|
|
12
|
-
margin-left: 0 !important;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/* Terminal Previews (Native PNGs)
|
|
16
|
-
* The images already contain the window chrome and shadows.
|
|
17
|
-
* We just need to center them and ensure they scale down on mobile.
|
|
18
|
-
*/
|
|
19
|
-
img[src*="images/"] {
|
|
20
|
-
display: block;
|
|
21
|
-
margin: 2em auto;
|
|
22
|
-
}
|
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
# Quickstart
|
|
6
|
-
|
|
7
|
-
Welcome to **ratatui_ruby**! This guide will help you get up and running with your first Terminal User Interface in Ruby.
|
|
8
|
-
|
|
9
|
-
## Installation
|
|
10
|
-
|
|
11
|
-
See [Installation in the README](../../README.md#installation) for setup instructions.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## Tutorials
|
|
15
|
-
|
|
16
|
-
### Basic Application
|
|
17
|
-
|
|
18
|
-
Here is a "Hello World" application that demonstrates the core lifecycle of a **ratatui_ruby** app.
|
|
19
|
-
|
|
20
|
-
<!-- SPDX-SnippetBegin -->
|
|
21
|
-
<!--
|
|
22
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
23
|
-
SPDX-License-Identifier: MIT-0
|
|
24
|
-
-->
|
|
25
|
-
<!-- SYNC:START:examples/verify_quickstart_lifecycle/app.rb:main -->
|
|
26
|
-
```ruby
|
|
27
|
-
# 1. Initialize the terminal
|
|
28
|
-
RatatuiRuby.init_terminal
|
|
29
|
-
|
|
30
|
-
begin
|
|
31
|
-
# The Main Loop
|
|
32
|
-
loop do
|
|
33
|
-
# 2. Create your UI (Immediate Mode)
|
|
34
|
-
# We define a Paragraph widget inside a Block with a title and borders.
|
|
35
|
-
view = RatatuiRuby::Widgets::Paragraph.new(
|
|
36
|
-
text: "Hello, Ratatui! Press 'q' to quit.",
|
|
37
|
-
alignment: :center,
|
|
38
|
-
block: RatatuiRuby::Widgets::Block.new(
|
|
39
|
-
title: "My Ruby TUI App",
|
|
40
|
-
title_alignment: :center,
|
|
41
|
-
borders: [:all],
|
|
42
|
-
border_style: { fg: "cyan" },
|
|
43
|
-
style: { fg: "white" }
|
|
44
|
-
)
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
# 3. Draw the UI
|
|
48
|
-
RatatuiRuby.draw do |frame|
|
|
49
|
-
frame.render_widget(view, frame.area)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# 4. Poll for events
|
|
53
|
-
case RatatuiRuby.poll_event
|
|
54
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
55
|
-
break
|
|
56
|
-
else
|
|
57
|
-
nil
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# 5. Guard against accidental output (optional but recommended)
|
|
61
|
-
# Wrap any code that might puts/warn to prevent screen corruption.
|
|
62
|
-
RatatuiRuby.guard_io do
|
|
63
|
-
# SomeChattyGem.do_something
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
ensure
|
|
67
|
-
# 6. Restore the terminal to its original state
|
|
68
|
-
RatatuiRuby.restore_terminal
|
|
69
|
-
end
|
|
70
|
-
```
|
|
71
|
-
<!-- SYNC:END -->
|
|
72
|
-
<!-- SPDX-SnippetEnd -->
|
|
73
|
-
|
|
74
|
-
[](../../examples/verify_quickstart_lifecycle/README.md)
|
|
75
|
-
|
|
76
|
-
#### How it works
|
|
77
|
-
|
|
78
|
-
1. **`RatatuiRuby.init_terminal`**: Enters raw mode and switches to the alternate screen.
|
|
79
|
-
2. **Immediate Mode UI**: On every iteration, describe your UI by creating `Data` objects (e.g., `Paragraph`, `Block`).
|
|
80
|
-
3. **`RatatuiRuby.draw { |frame| ... }`**: The block receives a `Frame` object as a canvas. Render widgets onto specific areas. Nothing is drawn until the block finishes, ensuring flicker-free updates.
|
|
81
|
-
4. **`RatatuiRuby.poll_event`**: Returns a typed `Event` object with predicates like `key?`, `mouse?`, `resize?`, etc. Returns `RatatuiRuby::Event::None` if no events are pending. Use predicates to check event type without pattern matching.
|
|
82
|
-
5. **`RatatuiRuby.guard_io { }`**: Wraps code that might write to stdout/stderr (e.g., chatty gems). Output is swallowed to prevent screen corruption. Optional but recommended for production apps.
|
|
83
|
-
6. **`RatatuiRuby.restore_terminal`**: Essential for leaving raw mode and returning to the shell. Always wrap your loop in `begin...ensure` to guarantee this runs.
|
|
84
|
-
|
|
85
|
-
### Simplified API
|
|
86
|
-
|
|
87
|
-
You can simplify your code by using `RatatuiRuby.run`. This method handles the terminal lifecycle for you, yielding a `TUI` object with factory methods for widgets.
|
|
88
|
-
|
|
89
|
-
<!-- SPDX-SnippetBegin -->
|
|
90
|
-
<!--
|
|
91
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
92
|
-
SPDX-License-Identifier: MIT-0
|
|
93
|
-
-->
|
|
94
|
-
<!-- SYNC:START:examples/verify_quickstart_dsl/app.rb:main -->
|
|
95
|
-
```ruby
|
|
96
|
-
# 1. Initialize the terminal, start the run loop, and ensure the terminal is restored.
|
|
97
|
-
RatatuiRuby.run do |tui|
|
|
98
|
-
loop do
|
|
99
|
-
# 2. Create your UI with methods instead of classes.
|
|
100
|
-
view = tui.paragraph(
|
|
101
|
-
text: "Hello, Ratatui! Press 'q' to quit.",
|
|
102
|
-
alignment: :center,
|
|
103
|
-
block: tui.block(
|
|
104
|
-
title: "My Ruby TUI App",
|
|
105
|
-
title_alignment: :center,
|
|
106
|
-
borders: [:all],
|
|
107
|
-
border_style: { fg: "cyan" },
|
|
108
|
-
style: { fg: "white" }
|
|
109
|
-
)
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
# 3. Use RatatuiRuby methods, too.
|
|
113
|
-
tui.draw do |frame|
|
|
114
|
-
frame.render_widget(view, frame.area)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# 4. Poll for events with pattern matching
|
|
118
|
-
case tui.poll_event
|
|
119
|
-
in { type: :key, code: "q" }
|
|
120
|
-
break
|
|
121
|
-
else
|
|
122
|
-
# Ignore other events
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
```
|
|
127
|
-
<!-- SYNC:END -->
|
|
128
|
-
<!-- SPDX-SnippetEnd -->
|
|
129
|
-
|
|
130
|
-
#### How it works
|
|
131
|
-
|
|
132
|
-
1. **`RatatuiRuby.run`**: This context manager initializes the terminal before the block starts and ensures `restore_terminal` is called when the block exits (even if an error occurs).
|
|
133
|
-
2. **Widget Shorthand**: The block yields a `TUI` object (here named `tui`). This object provides factory methods for every widget, allowing you to write `tui.paragraph(...)` instead of the more verbose `RatatuiRuby::Widgets::Paragraph.new(...)`.
|
|
134
|
-
3. **Method Shorthand**: The `TUI` object also provides aliases for module functions of `RatatuiRuby`, allowing you to write `tui.draw(...)` instead of the more verbose `RatatuiRuby.draw(...)`.
|
|
135
|
-
4. **Pattern Matching for Events**: Use `case...in` with pattern matching for elegant event dispatch. Always include an `else` clause at the end to catch unmatched event types (mouse, resize, paste, focus, etc.), otherwise Ruby raises `NoMatchingPatternError`.
|
|
136
|
-
|
|
137
|
-
For a deeper dive into the available application architectures (Manual vs Managed), see [Application Architecture](../concepts/application_architecture.md).
|
|
138
|
-
|
|
139
|
-
### Adding Layouts
|
|
140
|
-
|
|
141
|
-
Real-world applications often need to split the screen into multiple areas. `RatatuiRuby::Layout` lets you do this easily.
|
|
142
|
-
|
|
143
|
-
<!-- SPDX-SnippetBegin -->
|
|
144
|
-
<!--
|
|
145
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
146
|
-
SPDX-License-Identifier: MIT-0
|
|
147
|
-
-->
|
|
148
|
-
<!-- SYNC:START:examples/verify_quickstart_layout/app.rb:main -->
|
|
149
|
-
```ruby
|
|
150
|
-
loop do
|
|
151
|
-
tui.draw do |frame|
|
|
152
|
-
# 1. Split the screen
|
|
153
|
-
top, bottom = tui.layout_split(
|
|
154
|
-
frame.area,
|
|
155
|
-
direction: :vertical,
|
|
156
|
-
constraints: [
|
|
157
|
-
tui.constraint_percentage(75),
|
|
158
|
-
tui.constraint_percentage(25),
|
|
159
|
-
]
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
# 2. Render Top Widget
|
|
163
|
-
frame.render_widget(
|
|
164
|
-
tui.paragraph(
|
|
165
|
-
text: "Hello, Ratatui!",
|
|
166
|
-
alignment: :center,
|
|
167
|
-
block: tui.block(title: "Content", borders: [:all], border_style: { fg: "cyan" })
|
|
168
|
-
),
|
|
169
|
-
top
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# 3. Render Bottom Widget with Styled Text
|
|
173
|
-
# We use a Line of Spans to style specific characters
|
|
174
|
-
text_line = tui.text_line(
|
|
175
|
-
spans: [
|
|
176
|
-
tui.text_span(content: "Press '"),
|
|
177
|
-
tui.text_span(
|
|
178
|
-
content: "q",
|
|
179
|
-
style: tui.style(modifiers: [:bold, :underlined])
|
|
180
|
-
),
|
|
181
|
-
tui.text_span(content: "' to quit."),
|
|
182
|
-
],
|
|
183
|
-
alignment: :center
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
frame.render_widget(
|
|
187
|
-
tui.paragraph(
|
|
188
|
-
text: text_line,
|
|
189
|
-
block: tui.block(title: "Controls", borders: [:all])
|
|
190
|
-
),
|
|
191
|
-
bottom
|
|
192
|
-
)
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
case tui.poll_event
|
|
196
|
-
in { type: :key, code: "q" }
|
|
197
|
-
break
|
|
198
|
-
else
|
|
199
|
-
# Ignore other events
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
```
|
|
203
|
-
<!-- SYNC:END -->
|
|
204
|
-
<!-- SPDX-SnippetEnd -->
|
|
205
|
-
|
|
206
|
-
#### How it works
|
|
207
|
-
|
|
208
|
-
1. **`tui.layout_split` (`RatatuiRuby::Layout::Layout.split`)**: Takes an area (like `frame.area`) and splits it into multiple sub-areas based on constraints.
|
|
209
|
-
2. **`tui.constraint_*` (`RatatuiRuby::Layout::Constraint`)**: Defines how space is distributed (e.g., `percentage`, `length`, `min`, `max`).
|
|
210
|
-
3. **`Frame#render_widget(widget, rect)`**: You pass the specific area (like `top` or `bottom`) to render the widget into that exact region.
|
|
211
|
-
4. **`tui.text_span` (`RatatuiRuby::Text::Span`)**: Allows for rich styling within a single line of text.
|
|
212
|
-
|
|
213
|
-
[](../../examples/verify_quickstart_layout/README.md)
|
|
214
|
-
|
|
215
|
-
## Examples
|
|
216
|
-
|
|
217
|
-
These examples showcase the full power of **ratatui_ruby**. You can find their source code in the [examples directory](../../examples).
|
|
218
|
-
|
|
219
|
-
### Widget Demos
|
|
220
|
-
|
|
221
|
-
Focused examples for individual widgets. Each demonstrates a single widget and its configuration options.
|
|
222
|
-
|
|
223
|
-
| Widget | What it demonstrates |
|
|
224
|
-
| ------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
225
|
-
| [Bar Chart](../../examples/widget_barchart/app.rb) | Grouped bars, data visualization, custom bar styling |
|
|
226
|
-
| [Block](../../examples/widget_block/app.rb) | Borders, titles, padding, nested widgets |
|
|
227
|
-
| [Box](../../examples/widget_box/app.rb) | Block + Paragraph composition, text wrapping |
|
|
228
|
-
| [Calendar](../../examples/widget_calendar/app.rb) | Date highlighting, month display, event markers |
|
|
229
|
-
| [Chart](../../examples/widget_chart/app.rb) | Line/scatter plots, axes, legends, datasets |
|
|
230
|
-
| [Gauge](../../examples/widget_gauge/app.rb) | Progress bars, percentage display, unicode blocks |
|
|
231
|
-
| [Layout Split](../../examples/widget_layout_split/app.rb) | Constraint types, flex modes, responsive layouts |
|
|
232
|
-
| [Line Gauge](../../examples/widget_line_gauge/app.rb) | Horizontal progress, labels, thin-style gauges |
|
|
233
|
-
| [List](../../examples/widget_list/app.rb) | Selection, scrolling, highlight styles, rich text items |
|
|
234
|
-
| [Map](../../examples/widget_map/app.rb) | Canvas widget, world map rendering, coordinates |
|
|
235
|
-
| [Popup](../../examples/widget_popup/app.rb) | Clear widget, modal dialogs, overlay composition |
|
|
236
|
-
| [Ratatui Logo](../../examples/widget_ratatui_logo/app.rb) | Decorative branding widget |
|
|
237
|
-
| [Ratatui Mascot](../../examples/widget_ratatui_mascot/app.rb) | ASCII art Ferris mascot |
|
|
238
|
-
| [Rect](../../examples/widget_rect/app.rb) | Geometry helpers, area calculations, contains/intersection |
|
|
239
|
-
| [Rich Text](../../examples/widget_rich_text/app.rb) | Spans, lines, inline styling, mixed colors |
|
|
240
|
-
| [Scrollbar](../../examples/widget_scrollbar/app.rb) | Orientations, thumb/track styling, scroll state |
|
|
241
|
-
| [Scroll Text](../../examples/widget_scroll_text/app.rb) | Paragraph scrolling, viewport control, long content |
|
|
242
|
-
| [Sparkline](../../examples/widget_sparkline/app.rb) | Mini charts, time series, bar sets |
|
|
243
|
-
| [Style Colors](../../examples/widget_style_colors/app.rb) | Named colors, RGB, indexed 256-color palette |
|
|
244
|
-
| [Table](../../examples/widget_table/app.rb) | Row selection, column widths, per-cell styling |
|
|
245
|
-
| [Tabs](../../examples/widget_tabs/app.rb) | Tab navigation, highlighting, dividers |
|
|
246
|
-
| [Text Width](../../examples/widget_text_width/app.rb) | Unicode-aware width measurement, CJK support |
|
|
247
|
-
| [Canvas](../../examples/widget_canvas/app.rb) | Drawing shapes, markers, custom graphics |
|
|
248
|
-
| [Cell](../../examples/widget_cell/app.rb) | Buffer cell inspection, styling attributes |
|
|
249
|
-
| [Center](../../examples/widget_center/app.rb) | Centering content, horizontal/vertical alignment |
|
|
250
|
-
| [Overlay](../../examples/widget_overlay/app.rb) | Layering widgets, modal backgrounds |
|
|
251
|
-
| [Custom Render](../../examples/widget_render/app.rb) | Low-level Draw API, escape hatch for custom widgets |
|
|
252
|
-
|
|
253
|
-
### Sample Applications
|
|
254
|
-
|
|
255
|
-
These larger examples combine widgets into complete applications, demonstrating real-world TUI patterns and architectures.
|
|
256
|
-
|
|
257
|
-
| Application | Architecture | What you'll learn |
|
|
258
|
-
| ---------------------------------------------------------------------- | ----------------- | ------------------------------------------------------------ |
|
|
259
|
-
| [All Events](../../examples/app_all_events/app.rb) | Model-View-Update | Event handling, unidirectional data flow, scalable structure |
|
|
260
|
-
| [Color Picker](../../examples/app_color_picker/app.rb) | Component-Based | Hit testing, modal dialogs, encapsulated state |
|
|
261
|
-
| [Debugging Showcase](../../examples/app_debugging_showcase/app.rb) | Simple Loop | Remote debugging, Rust backtraces, improved error messages |
|
|
262
|
-
| [Login Form](../../examples/app_login_form/app.rb) | Overlay + Center | Modal forms, cursor positioning, text input |
|
|
263
|
-
| [Stateful Interaction](../../examples/app_stateful_interaction/app.rb) | State Objects | ListState/TableState, offset read-back, mouse click-to-row |
|
|
264
|
-
|
|
265
|
-
#### All Events
|
|
266
|
-
|
|
267
|
-
[](../../examples/app_all_events/README.md)
|
|
268
|
-
|
|
269
|
-
#### Color Picker
|
|
270
|
-
|
|
271
|
-
[](../../examples/app_color_picker/README.md)
|
|
272
|
-
|
|
273
|
-
#### Debugging Showcase
|
|
274
|
-
|
|
275
|
-
[](../../examples/app_debugging_showcase/README.md)
|
|
276
|
-
|
|
277
|
-
#### Login Form
|
|
278
|
-
|
|
279
|
-
[](../../examples/app_login_form/README.md)
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
## Next Steps
|
|
283
|
-
|
|
284
|
-
Now that you've seen what **ratatui_ruby** can do:
|
|
285
|
-
|
|
286
|
-
- **Deep dive**: Read the [Application Architecture](../concepts/application_architecture.md) guide for scaling patterns
|
|
287
|
-
- **Test your TUI**: See the [Testing Guide](../concepts/application_testing.md) for snapshot and style assertions
|
|
288
|
-
- **Avoid common mistakes**: See [Terminal Output During TUI Sessions](../troubleshooting/tui_output.md) to prevent screen corruption
|
|
289
|
-
- **Explore the API**: Browse the [full RDoc documentation](../index.md)
|
|
290
|
-
- **Learn the philosophy**: Read [Why RatatuiRuby?](./why.md) for comparisons and design decisions
|
|
291
|
-
- **Get help**: Join the [discussion mailing list](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss)
|
data/doc/getting_started/why.md
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
# Why RatatuiRuby?
|
|
6
|
-
|
|
7
|
-
The terminal is having a renaissance. Ruby deserves to be at the forefront.
|
|
8
|
-
|
|
9
|
-
**RatatuiRuby** is a high-performance, immediate-mode TUI engine that brings the power of Rust's [Ratatui](https://ratatui.rs) library directly into Ruby. No ports. No emulations. A native bridge to the industry-standard Rust crate.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## The Pitch
|
|
13
|
-
|
|
14
|
-
You want to build a terminal UI. You love Ruby. Your options were:
|
|
15
|
-
|
|
16
|
-
1. **Learn Go** for Bubble Tea
|
|
17
|
-
2. **Learn Rust** for Ratatui
|
|
18
|
-
3. **Use a pure-Ruby library** with limited performance
|
|
19
|
-
|
|
20
|
-
We built a fourth option: **Write Ruby. Run Rust.**
|
|
21
|
-
|
|
22
|
-
RatatuiRuby gives you Rust's layout engine, rendering speed, and battle-tested widgets — with Ruby's expressiveness, ecosystem, and joy.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
## RatatuiRuby vs. CharmRuby
|
|
26
|
-
|
|
27
|
-
[CharmRuby](https://charm-ruby.dev) is an excellent project by Marco Roth. It provides Ruby bindings to Charm's Go libraries (Bubble Tea, Lipgloss). The Ruby ecosystem is better because both projects exist.
|
|
28
|
-
|
|
29
|
-
So which one should you choose?
|
|
30
|
-
|
|
31
|
-
| | CharmRuby | RatatuiRuby |
|
|
32
|
-
|---|-----------|-------------|
|
|
33
|
-
| **Backend** | Go runtime | Rust (no runtime) |
|
|
34
|
-
| **Architecture** | Elm Architecture (MVU) | Immediate-mode + your choice |
|
|
35
|
-
| **GC Behavior** | Two GCs (Ruby + Go) | One GC (Ruby only) |
|
|
36
|
-
| **Rendering** | String manipulation | Constraint-based layout tree |
|
|
37
|
-
| **Best for** | Fans of Bubble Tea, MVU | Native performance, heavy-duty apps |
|
|
38
|
-
|
|
39
|
-
**What's a runtime?** A runtime is background machinery that a language needs to run. Go has one (for goroutines and garbage collection). Rust doesn't — it compiles to plain machine code. When you use Go bindings, you're running *two* runtimes in the same process (Ruby's and Go's), which adds complexity and memory overhead. With Rust bindings, there's only Ruby.
|
|
40
|
-
|
|
41
|
-
**Choose CharmRuby** if you prefer Charm's aesthetics or are migrating existing Bubble Tea code.
|
|
42
|
-
|
|
43
|
-
**Choose RatatuiRuby** if you want zero-overhead native performance and architectural freedom. RatatuiRuby doesn't force a framework — you can build MVU, component-based, or any pattern you prefer.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
## Why Not Just Write Rust?
|
|
47
|
-
|
|
48
|
-
Rust is amazing. It's also strict.
|
|
49
|
-
|
|
50
|
-
The borrow checker enforces memory safety. That's great for systems programming. It's painful for UI iteration. Moving a sidebar, changing a color, or swapping a widget often requires refactoring ownership chains.
|
|
51
|
-
|
|
52
|
-
With RatatuiRuby, you just change the object. You get Rust's performance where it matters — rendering — and Ruby's flexibility where it counts — designing.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
## Why Not Just Write Go?
|
|
56
|
-
|
|
57
|
-
Go is pragmatic. But using Go bindings means running *two* runtimes in the same process: Ruby's and Go's. That adds complexity and memory overhead.
|
|
58
|
-
|
|
59
|
-
With RatatuiRuby, there's only Ruby. Rust compiles to plain machine code with no runtime — it integrates seamlessly.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
## Why Ruby?
|
|
63
|
-
|
|
64
|
-
[Ruby isn't just another language](https://www.ruby-lang.org/en/). It's an ecosystem:
|
|
65
|
-
|
|
66
|
-
- **[ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html)** — Query your database with elegant, chainable methods
|
|
67
|
-
- **[RSpec](https://rspec.info/)** — Write expressive, readable tests with `describe`, `it`, and `expect`
|
|
68
|
-
- **[Blocks](https://docs.ruby-lang.org/en/4.0/syntax/calling_methods_rdoc.html#label-Block+Argument)** — Pass behavior to methods with `do...end`, the heart of Ruby's expressiveness
|
|
69
|
-
- **[Metaprogramming](https://docs.ruby-lang.org/en/4.0/Module.html#method-i-class_eval)** — Define methods dynamically, build DSLs, and write code that writes code
|
|
70
|
-
- **[Bundler](https://bundler.io/)** — Access 180,000+ gems with a single `bundle add`
|
|
71
|
-
|
|
72
|
-
Build a dashboard for your Rails app. Monitor your Sidekiq jobs. Create developer tools in the same language as the code they inspect.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
## The Philosophy: A Solid Foundation
|
|
76
|
-
|
|
77
|
-
RatatuiRuby is a **low-level engine**. It provides raw primitives — Layouts, Blocks, Text, Tables, Charts — to build anything.
|
|
78
|
-
|
|
79
|
-
It doesn't force a framework on you. You can use:
|
|
80
|
-
- **Model-View-Update** for dashboards and data displays
|
|
81
|
-
- **Component-based** patterns for interactive tools
|
|
82
|
-
- **Your own architecture** for everything else
|
|
83
|
-
|
|
84
|
-
This is the foundation for Ruby's next generation of TUI tools, dashboards, and interactive scripts.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
## Get Started
|
|
88
|
-
|
|
89
|
-
Ready to build?
|
|
90
|
-
|
|
91
|
-
- [Quickstart Guide](./quickstart.md) — Your first app in 5 minutes
|
|
92
|
-
- [Widget Gallery](./quickstart.md#widget-demos) — See what's possible
|
|
93
|
-
- [Application Architecture](../concepts/application_architecture.md) — Patterns for scaling
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/doc/images/widget_block.png
DELETED
|
Binary file
|
data/doc/images/widget_box.png
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/doc/images/widget_cell.png
DELETED
|
Binary file
|
|
Binary file
|
data/doc/images/widget_chart.png
DELETED
|
Binary file
|
data/doc/images/widget_gauge.png
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/doc/images/widget_list.png
DELETED
|
Binary file
|
data/doc/images/widget_map.png
DELETED
|
Binary file
|
|
Binary file
|
data/doc/images/widget_popup.png
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/doc/images/widget_rect.png
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/doc/images/widget_table.png
DELETED
|
Binary file
|
data/doc/images/widget_tabs.png
DELETED
|
Binary file
|
|
Binary file
|