ratatui_ruby 0.9.0 → 0.10.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 +2 -1
- data/CHANGELOG.md +122 -0
- data/REUSE.toml +5 -0
- data/Rakefile +1 -1
- data/Steepfile +49 -0
- data/doc/concepts/debugging.md +401 -0
- data/doc/getting_started/quickstart.md +8 -3
- data/doc/images/app_all_events.png +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_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/troubleshooting/async.md +4 -0
- data/examples/app_debugging_showcase/README.md +119 -0
- data/examples/app_debugging_showcase/app.rb +318 -0
- data/examples/widget_canvas/app.rb +19 -14
- data/examples/widget_gauge/app.rb +18 -3
- data/examples/widget_layout_split/app.rb +16 -4
- data/examples/widget_list/app.rb +22 -6
- data/examples/widget_rect/app.rb +7 -6
- data/examples/widget_rich_text/app.rb +62 -37
- data/examples/widget_style_colors/app.rb +26 -47
- data/examples/widget_table/app.rb +28 -5
- data/examples/widget_text_width/app.rb +6 -4
- data/ext/ratatui_ruby/Cargo.lock +48 -1
- data/ext/ratatui_ruby/Cargo.toml +6 -2
- data/ext/ratatui_ruby/src/color.rs +82 -0
- data/ext/ratatui_ruby/src/errors.rs +28 -0
- data/ext/ratatui_ruby/src/events.rs +16 -14
- data/ext/ratatui_ruby/src/lib.rs +56 -0
- data/ext/ratatui_ruby/src/rendering.rs +3 -1
- data/ext/ratatui_ruby/src/style.rs +48 -21
- data/ext/ratatui_ruby/src/terminal.rs +40 -9
- data/ext/ratatui_ruby/src/text.rs +21 -9
- data/ext/ratatui_ruby/src/widgets/chart.rs +2 -1
- data/ext/ratatui_ruby/src/widgets/layout.rs +90 -2
- data/ext/ratatui_ruby/src/widgets/list.rs +6 -5
- data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
- data/ext/ratatui_ruby/src/widgets/table.rs +7 -6
- data/ext/ratatui_ruby/src/widgets/table_state.rs +55 -0
- data/ext/ratatui_ruby/src/widgets/tabs.rs +3 -2
- data/lib/ratatui_ruby/buffer/cell.rb +25 -15
- data/lib/ratatui_ruby/buffer.rb +134 -2
- data/lib/ratatui_ruby/cell.rb +13 -5
- data/lib/ratatui_ruby/debug.rb +215 -0
- data/lib/ratatui_ruby/event/key.rb +3 -2
- data/lib/ratatui_ruby/event/sync.rb +52 -0
- data/lib/ratatui_ruby/event.rb +7 -1
- data/lib/ratatui_ruby/layout/constraint.rb +184 -0
- data/lib/ratatui_ruby/layout/layout.rb +119 -13
- data/lib/ratatui_ruby/layout/position.rb +55 -0
- data/lib/ratatui_ruby/layout/rect.rb +188 -0
- data/lib/ratatui_ruby/layout/size.rb +55 -0
- data/lib/ratatui_ruby/layout.rb +4 -0
- data/lib/ratatui_ruby/style/color.rb +149 -0
- data/lib/ratatui_ruby/style/style.rb +51 -4
- data/lib/ratatui_ruby/style.rb +2 -0
- data/lib/ratatui_ruby/symbols.rb +435 -0
- data/lib/ratatui_ruby/synthetic_events.rb +86 -0
- data/lib/ratatui_ruby/table_state.rb +51 -0
- data/lib/ratatui_ruby/terminal_lifecycle.rb +2 -1
- data/lib/ratatui_ruby/test_helper/event_injection.rb +34 -1
- data/lib/ratatui_ruby/test_helper.rb +9 -0
- data/lib/ratatui_ruby/text/line.rb +245 -0
- data/lib/ratatui_ruby/text/span.rb +158 -0
- data/lib/ratatui_ruby/text.rb +99 -0
- data/lib/ratatui_ruby/tui/canvas_factories.rb +103 -0
- data/lib/ratatui_ruby/tui/core.rb +13 -2
- data/lib/ratatui_ruby/tui/layout_factories.rb +50 -3
- data/lib/ratatui_ruby/tui/state_factories.rb +42 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +40 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +135 -60
- data/lib/ratatui_ruby/tui.rb +22 -1
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +30 -20
- data/lib/ratatui_ruby/widgets/block.rb +14 -6
- data/lib/ratatui_ruby/widgets/calendar.rb +2 -0
- data/lib/ratatui_ruby/widgets/canvas.rb +56 -0
- data/lib/ratatui_ruby/widgets/cell.rb +2 -0
- data/lib/ratatui_ruby/widgets/center.rb +2 -0
- data/lib/ratatui_ruby/widgets/chart.rb +6 -0
- data/lib/ratatui_ruby/widgets/clear.rb +2 -0
- data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +2 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +61 -3
- data/lib/ratatui_ruby/widgets/line_gauge.rb +66 -4
- data/lib/ratatui_ruby/widgets/list.rb +87 -3
- data/lib/ratatui_ruby/widgets/list_item.rb +2 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +2 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +4 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -0
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -0
- data/lib/ratatui_ruby/widgets/row.rb +45 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -0
- data/lib/ratatui_ruby/widgets/shape/label.rb +2 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +21 -13
- data/lib/ratatui_ruby/widgets/table.rb +13 -3
- data/lib/ratatui_ruby/widgets/tabs.rb +6 -4
- data/lib/ratatui_ruby/widgets.rb +1 -0
- data/lib/ratatui_ruby.rb +51 -16
- data/sig/examples/app_all_events/model/app_model.rbs +23 -0
- data/sig/examples/app_all_events/model/event_entry.rbs +15 -8
- data/sig/examples/app_all_events/model/timestamp.rbs +1 -1
- data/sig/examples/app_all_events/view.rbs +1 -1
- data/sig/examples/app_stateful_interaction/app.rbs +5 -5
- data/sig/examples/widget_block_demo/app.rbs +6 -6
- data/sig/manifest.yaml +5 -0
- data/sig/patches/data.rbs +26 -0
- data/sig/patches/debugger__.rbs +8 -0
- data/sig/ratatui_ruby/buffer/cell.rbs +46 -0
- data/sig/ratatui_ruby/buffer.rbs +18 -0
- data/sig/ratatui_ruby/cell.rbs +44 -0
- data/sig/ratatui_ruby/clear.rbs +18 -0
- data/sig/ratatui_ruby/constraint.rbs +26 -0
- data/sig/ratatui_ruby/debug.rbs +45 -0
- data/sig/ratatui_ruby/draw.rbs +30 -0
- data/sig/ratatui_ruby/event.rbs +68 -8
- data/sig/ratatui_ruby/frame.rbs +4 -4
- data/sig/ratatui_ruby/interfaces.rbs +25 -0
- data/sig/ratatui_ruby/layout/constraint.rbs +39 -0
- data/sig/ratatui_ruby/layout/layout.rbs +45 -0
- data/sig/ratatui_ruby/layout/position.rbs +18 -0
- data/sig/ratatui_ruby/layout/rect.rbs +64 -0
- data/sig/ratatui_ruby/layout/size.rbs +18 -0
- data/sig/ratatui_ruby/output_guard.rbs +23 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +83 -4
- data/sig/ratatui_ruby/rect.rbs +17 -0
- data/sig/ratatui_ruby/style/color.rbs +22 -0
- data/sig/ratatui_ruby/style/style.rbs +29 -0
- data/sig/ratatui_ruby/symbols.rbs +141 -0
- data/sig/ratatui_ruby/synthetic_events.rbs +21 -0
- data/sig/ratatui_ruby/table_state.rbs +6 -0
- data/sig/ratatui_ruby/terminal_lifecycle.rbs +31 -0
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +2 -2
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +22 -3
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +8 -1
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -3
- data/sig/ratatui_ruby/text/line.rbs +27 -0
- data/sig/ratatui_ruby/text/span.rbs +23 -0
- data/sig/ratatui_ruby/text.rbs +12 -0
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +1 -1
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +23 -5
- data/sig/ratatui_ruby/tui/core.rbs +2 -2
- data/sig/ratatui_ruby/tui/layout_factories.rbs +16 -2
- data/sig/ratatui_ruby/tui/state_factories.rbs +8 -3
- data/sig/ratatui_ruby/tui/style_factories.rbs +3 -1
- data/sig/ratatui_ruby/tui/text_factories.rbs +7 -4
- data/sig/ratatui_ruby/tui/widget_factories.rbs +123 -30
- data/sig/ratatui_ruby/widgets/bar_chart.rbs +95 -0
- data/sig/ratatui_ruby/widgets/block.rbs +51 -0
- data/sig/ratatui_ruby/widgets/calendar.rbs +45 -0
- data/sig/ratatui_ruby/widgets/canvas.rbs +95 -0
- data/sig/ratatui_ruby/widgets/chart.rbs +91 -0
- data/sig/ratatui_ruby/widgets/coerceable_widget.rbs +26 -0
- data/sig/ratatui_ruby/widgets/gauge.rbs +44 -0
- data/sig/ratatui_ruby/widgets/line_gauge.rbs +48 -0
- data/sig/ratatui_ruby/widgets/list.rbs +63 -0
- data/sig/ratatui_ruby/widgets/misc.rbs +158 -0
- data/sig/ratatui_ruby/widgets/paragraph.rbs +45 -0
- data/sig/ratatui_ruby/widgets/row.rbs +43 -0
- data/sig/ratatui_ruby/widgets/scrollbar.rbs +53 -0
- data/sig/ratatui_ruby/widgets/shape/label.rbs +37 -0
- data/sig/ratatui_ruby/widgets/sparkline.rbs +45 -0
- data/sig/ratatui_ruby/widgets/table.rbs +78 -0
- data/sig/ratatui_ruby/widgets/tabs.rbs +44 -0
- data/sig/ratatui_ruby/{schema/list_item.rbs → widgets.rbs} +4 -4
- data/tasks/steep.rake +11 -0
- metadata +82 -63
- data/doc/contributors/v1.0.0_blockers.md +0 -876
- data/doc/troubleshooting/debugging.md +0 -101
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +0 -47
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +0 -25
- data/lib/ratatui_ruby/schema/bar_chart.rb +0 -287
- data/lib/ratatui_ruby/schema/block.rb +0 -198
- data/lib/ratatui_ruby/schema/calendar.rb +0 -84
- data/lib/ratatui_ruby/schema/canvas.rb +0 -239
- data/lib/ratatui_ruby/schema/center.rb +0 -67
- data/lib/ratatui_ruby/schema/chart.rb +0 -159
- data/lib/ratatui_ruby/schema/clear.rb +0 -62
- data/lib/ratatui_ruby/schema/constraint.rb +0 -151
- data/lib/ratatui_ruby/schema/cursor.rb +0 -50
- data/lib/ratatui_ruby/schema/gauge.rb +0 -72
- data/lib/ratatui_ruby/schema/layout.rb +0 -122
- data/lib/ratatui_ruby/schema/line_gauge.rb +0 -80
- data/lib/ratatui_ruby/schema/list.rb +0 -135
- data/lib/ratatui_ruby/schema/list_item.rb +0 -51
- data/lib/ratatui_ruby/schema/overlay.rb +0 -51
- data/lib/ratatui_ruby/schema/paragraph.rb +0 -107
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +0 -31
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +0 -36
- data/lib/ratatui_ruby/schema/rect.rb +0 -174
- data/lib/ratatui_ruby/schema/row.rb +0 -76
- data/lib/ratatui_ruby/schema/scrollbar.rb +0 -143
- data/lib/ratatui_ruby/schema/shape/label.rb +0 -76
- data/lib/ratatui_ruby/schema/sparkline.rb +0 -142
- data/lib/ratatui_ruby/schema/style.rb +0 -97
- data/lib/ratatui_ruby/schema/table.rb +0 -141
- data/lib/ratatui_ruby/schema/tabs.rb +0 -85
- data/lib/ratatui_ruby/schema/text.rb +0 -217
- data/sig/examples/app_all_events/model/events.rbs +0 -15
- data/sig/examples/app_all_events/view_state.rbs +0 -21
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +0 -22
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +0 -19
- data/sig/ratatui_ruby/schema/bar_chart.rbs +0 -38
- data/sig/ratatui_ruby/schema/block.rbs +0 -18
- data/sig/ratatui_ruby/schema/calendar.rbs +0 -23
- data/sig/ratatui_ruby/schema/canvas.rbs +0 -81
- data/sig/ratatui_ruby/schema/center.rbs +0 -17
- data/sig/ratatui_ruby/schema/chart.rbs +0 -39
- data/sig/ratatui_ruby/schema/constraint.rbs +0 -22
- data/sig/ratatui_ruby/schema/cursor.rbs +0 -16
- data/sig/ratatui_ruby/schema/draw.rbs +0 -33
- data/sig/ratatui_ruby/schema/gauge.rbs +0 -23
- data/sig/ratatui_ruby/schema/layout.rbs +0 -27
- data/sig/ratatui_ruby/schema/line_gauge.rbs +0 -24
- data/sig/ratatui_ruby/schema/list.rbs +0 -28
- data/sig/ratatui_ruby/schema/overlay.rbs +0 -15
- data/sig/ratatui_ruby/schema/paragraph.rbs +0 -20
- data/sig/ratatui_ruby/schema/ratatui_logo.rbs +0 -14
- data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +0 -17
- data/sig/ratatui_ruby/schema/rect.rbs +0 -48
- data/sig/ratatui_ruby/schema/row.rbs +0 -28
- data/sig/ratatui_ruby/schema/scrollbar.rbs +0 -42
- data/sig/ratatui_ruby/schema/sparkline.rbs +0 -22
- data/sig/ratatui_ruby/schema/style.rbs +0 -19
- data/sig/ratatui_ruby/schema/table.rbs +0 -32
- data/sig/ratatui_ruby/schema/tabs.rbs +0 -21
- data/sig/ratatui_ruby/schema/text.rbs +0 -31
- /data/lib/ratatui_ruby/{schema/draw.rb → draw.rb} +0 -0
|
@@ -30,6 +30,48 @@ module RatatuiRuby
|
|
|
30
30
|
def scrollbar_state(...)
|
|
31
31
|
ScrollbarState.new(...)
|
|
32
32
|
end
|
|
33
|
+
|
|
34
|
+
# =====================================
|
|
35
|
+
# State Dispatcher (TIMTOWTDI)
|
|
36
|
+
# =====================================
|
|
37
|
+
|
|
38
|
+
# Creates a state object by type symbol.
|
|
39
|
+
#
|
|
40
|
+
# Stateful widgets need companion state objects. When building dynamic UIs,
|
|
41
|
+
# the state type must be determined at runtime.
|
|
42
|
+
#
|
|
43
|
+
# This dispatcher routes state creation through a single entry point.
|
|
44
|
+
# Pass the type as a symbol and the remaining parameters.
|
|
45
|
+
#
|
|
46
|
+
# Use it for generic list/table factories or config-driven components.
|
|
47
|
+
#
|
|
48
|
+
# Also available as: <tt>tui.list_state</tt>, <tt>tui.table_state</tt>
|
|
49
|
+
#
|
|
50
|
+
# === Examples
|
|
51
|
+
#
|
|
52
|
+
#--
|
|
53
|
+
# SPDX-SnippetBegin
|
|
54
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
55
|
+
# SPDX-License-Identifier: MIT-0
|
|
56
|
+
#++
|
|
57
|
+
# tui.state(:list, nil) # => ListState with no selection
|
|
58
|
+
# tui.state(:table, 0) # => TableState with row 0 selected
|
|
59
|
+
# tui.state(:scrollbar, 100) # => ScrollbarState with 100 content length
|
|
60
|
+
#--
|
|
61
|
+
# SPDX-SnippetEnd
|
|
62
|
+
#++
|
|
63
|
+
#
|
|
64
|
+
# @param type [Symbol] State type: :list, :table, :scrollbar
|
|
65
|
+
# @return [ListState, TableState, ScrollbarState]
|
|
66
|
+
def state(type, arg = nil)
|
|
67
|
+
case type
|
|
68
|
+
when :list then list_state(arg)
|
|
69
|
+
when :table then table_state(arg)
|
|
70
|
+
when :scrollbar then scrollbar_state(arg || 0)
|
|
71
|
+
else
|
|
72
|
+
raise ArgumentError, "Unknown state type: :#{type}. Valid types: :list, :table, :scrollbar"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
33
75
|
end
|
|
34
76
|
end
|
|
35
77
|
end
|
|
@@ -41,6 +41,46 @@ module RatatuiRuby
|
|
|
41
41
|
def text_width(string)
|
|
42
42
|
Text.width(string)
|
|
43
43
|
end
|
|
44
|
+
|
|
45
|
+
# =====================================
|
|
46
|
+
# Text Dispatcher (TIMTOWTDI)
|
|
47
|
+
# =====================================
|
|
48
|
+
|
|
49
|
+
# Creates a text element by type symbol.
|
|
50
|
+
#
|
|
51
|
+
# Building text programmatically requires knowing which method to call.
|
|
52
|
+
# When the text type comes from config or user input, you need a dispatcher.
|
|
53
|
+
#
|
|
54
|
+
# This method routes text creation through a single entry point.
|
|
55
|
+
# Pass the type as a symbol and the remaining parameters as kwargs.
|
|
56
|
+
#
|
|
57
|
+
# Use it for dynamic text generation or config-driven rendering.
|
|
58
|
+
#
|
|
59
|
+
# Also available as: <tt>tui.span</tt>, <tt>tui.text_span</tt>
|
|
60
|
+
#
|
|
61
|
+
# === Examples
|
|
62
|
+
#
|
|
63
|
+
#--
|
|
64
|
+
# SPDX-SnippetBegin
|
|
65
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
66
|
+
# SPDX-License-Identifier: MIT-0
|
|
67
|
+
#++
|
|
68
|
+
# tui.text(:span, content: "Hello", style: Style.with(fg: :blue))
|
|
69
|
+
# tui.text(:line, spans: [tui.span(content: "World")])
|
|
70
|
+
#--
|
|
71
|
+
# SPDX-SnippetEnd
|
|
72
|
+
#++
|
|
73
|
+
#
|
|
74
|
+
# @param type [Symbol] Text type: :span, :line
|
|
75
|
+
# @return [Text::Span, Text::Line]
|
|
76
|
+
def text(type, **)
|
|
77
|
+
case type
|
|
78
|
+
when :span then text_span(**)
|
|
79
|
+
when :line then text_line(**)
|
|
80
|
+
else
|
|
81
|
+
raise ArgumentError, "Unknown text type: #{type.inspect}. Valid types: :span, :line"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
44
84
|
end
|
|
45
85
|
end
|
|
46
86
|
end
|
|
@@ -12,185 +12,260 @@ module RatatuiRuby
|
|
|
12
12
|
# Provides convenient access to all Widgets::* classes without
|
|
13
13
|
# fully qualifying the class names. This is the largest mixin,
|
|
14
14
|
# covering all renderable UI components.
|
|
15
|
+
#
|
|
16
|
+
# All factories use DWIM hash coercion: both `tui.table(hash)` and
|
|
17
|
+
# `tui.table(**hash)` work correctly.
|
|
15
18
|
module WidgetFactories
|
|
16
19
|
# Creates a Widgets::Block.
|
|
17
20
|
# @return [Widgets::Block]
|
|
18
|
-
def block(
|
|
19
|
-
Widgets::Block.
|
|
21
|
+
def block(first = nil, **kwargs)
|
|
22
|
+
Widgets::Block.coerce_args(first, kwargs)
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
# Creates a Widgets::Paragraph.
|
|
23
26
|
# @return [Widgets::Paragraph]
|
|
24
|
-
def paragraph(
|
|
25
|
-
Widgets::Paragraph.
|
|
27
|
+
def paragraph(first = nil, **kwargs)
|
|
28
|
+
Widgets::Paragraph.coerce_args(first, kwargs)
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
# Creates a Widgets::List.
|
|
29
32
|
# @return [Widgets::List]
|
|
30
|
-
def list(
|
|
31
|
-
Widgets::List.
|
|
33
|
+
def list(first = nil, **kwargs)
|
|
34
|
+
Widgets::List.coerce_args(first, kwargs)
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
# Creates a Widgets::ListItem.
|
|
35
38
|
# @return [Widgets::ListItem]
|
|
36
|
-
def list_item(
|
|
37
|
-
Widgets::ListItem.
|
|
39
|
+
def list_item(first = nil, **kwargs)
|
|
40
|
+
Widgets::ListItem.coerce_args(first, kwargs)
|
|
38
41
|
end
|
|
39
42
|
|
|
43
|
+
# Creates a Widgets::ListItem (DWIM alias).
|
|
44
|
+
#
|
|
45
|
+
# Terse alias for list_item. Clear in list context.
|
|
46
|
+
#
|
|
47
|
+
# @return [Widgets::ListItem]
|
|
48
|
+
alias item list_item
|
|
49
|
+
|
|
40
50
|
# Creates a Widgets::Table.
|
|
41
51
|
# @return [Widgets::Table]
|
|
42
|
-
def table(
|
|
43
|
-
Widgets::Table.
|
|
52
|
+
def table(first = nil, **kwargs)
|
|
53
|
+
Widgets::Table.coerce_args(first, kwargs)
|
|
44
54
|
end
|
|
45
55
|
|
|
46
56
|
# Creates a Widgets::Row (for Table rows).
|
|
47
57
|
# @return [Widgets::Row]
|
|
48
|
-
def row(
|
|
49
|
-
Widgets::Row.
|
|
58
|
+
def row(first = nil, **kwargs)
|
|
59
|
+
Widgets::Row.coerce_args(first, kwargs)
|
|
50
60
|
end
|
|
51
61
|
|
|
52
62
|
# Creates a Widgets::Row (alias for table row).
|
|
53
63
|
# @return [Widgets::Row]
|
|
54
|
-
def table_row(
|
|
55
|
-
Widgets::Row.
|
|
64
|
+
def table_row(first = nil, **kwargs)
|
|
65
|
+
Widgets::Row.coerce_args(first, kwargs)
|
|
56
66
|
end
|
|
57
67
|
|
|
58
68
|
# Creates a Widgets::Cell (for Table cells).
|
|
59
69
|
# @return [Widgets::Cell]
|
|
60
|
-
def table_cell(
|
|
61
|
-
Widgets::Cell.
|
|
70
|
+
def table_cell(first = nil, **kwargs)
|
|
71
|
+
Widgets::Cell.coerce_args(first, kwargs)
|
|
62
72
|
end
|
|
63
73
|
|
|
64
74
|
# Creates a Widgets::Tabs.
|
|
65
75
|
# @return [Widgets::Tabs]
|
|
66
|
-
def tabs(
|
|
67
|
-
Widgets::Tabs.
|
|
76
|
+
def tabs(first = nil, **kwargs)
|
|
77
|
+
Widgets::Tabs.coerce_args(first, kwargs)
|
|
68
78
|
end
|
|
69
79
|
|
|
70
80
|
# Creates a Widgets::Gauge.
|
|
71
81
|
# @return [Widgets::Gauge]
|
|
72
|
-
def gauge(
|
|
73
|
-
Widgets::Gauge.
|
|
82
|
+
def gauge(first = nil, **kwargs)
|
|
83
|
+
Widgets::Gauge.coerce_args(first, kwargs)
|
|
74
84
|
end
|
|
75
85
|
|
|
76
86
|
# Creates a Widgets::LineGauge.
|
|
77
87
|
# @return [Widgets::LineGauge]
|
|
78
|
-
def line_gauge(
|
|
79
|
-
Widgets::LineGauge.
|
|
88
|
+
def line_gauge(first = nil, **kwargs)
|
|
89
|
+
Widgets::LineGauge.coerce_args(first, kwargs)
|
|
80
90
|
end
|
|
81
91
|
|
|
82
92
|
# Creates a Widgets::Sparkline.
|
|
83
93
|
# @return [Widgets::Sparkline]
|
|
84
|
-
def sparkline(
|
|
85
|
-
Widgets::Sparkline.
|
|
94
|
+
def sparkline(first = nil, **kwargs)
|
|
95
|
+
Widgets::Sparkline.coerce_args(first, kwargs)
|
|
86
96
|
end
|
|
87
97
|
|
|
88
98
|
# Creates a Widgets::BarChart.
|
|
89
99
|
# @return [Widgets::BarChart]
|
|
90
|
-
def bar_chart(
|
|
91
|
-
Widgets::BarChart.
|
|
100
|
+
def bar_chart(first = nil, **kwargs)
|
|
101
|
+
Widgets::BarChart.coerce_args(first, kwargs)
|
|
92
102
|
end
|
|
93
103
|
|
|
94
104
|
# Creates a Widgets::BarChart::Bar.
|
|
95
105
|
# @return [Widgets::BarChart::Bar]
|
|
96
|
-
def bar(
|
|
97
|
-
Widgets::BarChart::Bar.
|
|
106
|
+
def bar(first = nil, **kwargs)
|
|
107
|
+
Widgets::BarChart::Bar.coerce_args(first, kwargs)
|
|
98
108
|
end
|
|
99
109
|
|
|
100
110
|
# Creates a Widgets::BarChart::BarGroup.
|
|
101
111
|
# @return [Widgets::BarChart::BarGroup]
|
|
102
|
-
def bar_group(
|
|
103
|
-
Widgets::BarChart::BarGroup.
|
|
112
|
+
def bar_group(first = nil, **kwargs)
|
|
113
|
+
Widgets::BarChart::BarGroup.coerce_args(first, kwargs)
|
|
104
114
|
end
|
|
105
115
|
|
|
106
116
|
# Creates a Widgets::BarChart::Bar (alias).
|
|
107
117
|
# @return [Widgets::BarChart::Bar]
|
|
108
|
-
def bar_chart_bar(
|
|
109
|
-
Widgets::BarChart::Bar.
|
|
118
|
+
def bar_chart_bar(first = nil, **kwargs)
|
|
119
|
+
Widgets::BarChart::Bar.coerce_args(first, kwargs)
|
|
110
120
|
end
|
|
111
121
|
|
|
112
122
|
# Creates a Widgets::BarChart::BarGroup (alias).
|
|
113
123
|
# @return [Widgets::BarChart::BarGroup]
|
|
114
|
-
def bar_chart_bar_group(
|
|
115
|
-
Widgets::BarChart::BarGroup.
|
|
124
|
+
def bar_chart_bar_group(first = nil, **kwargs)
|
|
125
|
+
Widgets::BarChart::BarGroup.coerce_args(first, kwargs)
|
|
116
126
|
end
|
|
117
127
|
|
|
118
128
|
# Creates a Widgets::Chart.
|
|
119
129
|
# @return [Widgets::Chart]
|
|
120
|
-
def chart(
|
|
121
|
-
Widgets::Chart.
|
|
130
|
+
def chart(first = nil, **kwargs)
|
|
131
|
+
Widgets::Chart.coerce_args(first, kwargs)
|
|
122
132
|
end
|
|
123
133
|
|
|
124
134
|
# Creates a Widgets::Dataset.
|
|
125
135
|
# @return [Widgets::Dataset]
|
|
126
|
-
def dataset(
|
|
127
|
-
Widgets::Dataset.
|
|
136
|
+
def dataset(first = nil, **kwargs)
|
|
137
|
+
Widgets::Dataset.coerce_args(first, kwargs)
|
|
128
138
|
end
|
|
129
139
|
|
|
130
140
|
# Creates a Widgets::Axis.
|
|
131
141
|
# @return [Widgets::Axis]
|
|
132
|
-
def axis(
|
|
133
|
-
Widgets::Axis.
|
|
142
|
+
def axis(first = nil, **kwargs)
|
|
143
|
+
Widgets::Axis.coerce_args(first, kwargs)
|
|
134
144
|
end
|
|
135
145
|
|
|
136
146
|
# Creates a Widgets::Scrollbar.
|
|
137
147
|
# @return [Widgets::Scrollbar]
|
|
138
|
-
def scrollbar(
|
|
139
|
-
Widgets::Scrollbar.
|
|
148
|
+
def scrollbar(first = nil, **kwargs)
|
|
149
|
+
Widgets::Scrollbar.coerce_args(first, kwargs)
|
|
140
150
|
end
|
|
141
151
|
|
|
142
152
|
# Creates a Widgets::Calendar.
|
|
143
153
|
# @return [Widgets::Calendar]
|
|
144
|
-
def calendar(
|
|
145
|
-
Widgets::Calendar.
|
|
154
|
+
def calendar(first = nil, **kwargs)
|
|
155
|
+
Widgets::Calendar.coerce_args(first, kwargs)
|
|
146
156
|
end
|
|
147
157
|
|
|
148
158
|
# Creates a Widgets::Canvas.
|
|
149
159
|
# @return [Widgets::Canvas]
|
|
150
|
-
def canvas(
|
|
151
|
-
Widgets::Canvas.
|
|
160
|
+
def canvas(first = nil, **kwargs)
|
|
161
|
+
Widgets::Canvas.coerce_args(first, kwargs)
|
|
152
162
|
end
|
|
153
163
|
|
|
154
164
|
# Creates a Widgets::Clear.
|
|
155
165
|
# @return [Widgets::Clear]
|
|
156
|
-
def clear(
|
|
157
|
-
Widgets::Clear.
|
|
166
|
+
def clear(first = nil, **kwargs)
|
|
167
|
+
Widgets::Clear.coerce_args(first, kwargs)
|
|
158
168
|
end
|
|
159
169
|
|
|
160
170
|
# Creates a Widgets::Cursor.
|
|
161
171
|
# @return [Widgets::Cursor]
|
|
162
|
-
def cursor(
|
|
163
|
-
Widgets::Cursor.
|
|
172
|
+
def cursor(first = nil, **kwargs)
|
|
173
|
+
Widgets::Cursor.coerce_args(first, kwargs)
|
|
164
174
|
end
|
|
165
175
|
|
|
166
176
|
# Creates a Widgets::Overlay.
|
|
167
177
|
# @return [Widgets::Overlay]
|
|
168
|
-
def overlay(
|
|
169
|
-
Widgets::Overlay.
|
|
178
|
+
def overlay(first = nil, **kwargs)
|
|
179
|
+
Widgets::Overlay.coerce_args(first, kwargs)
|
|
170
180
|
end
|
|
171
181
|
|
|
172
182
|
# Creates a Widgets::Center.
|
|
173
183
|
# @return [Widgets::Center]
|
|
174
|
-
def center(
|
|
175
|
-
Widgets::Center.
|
|
184
|
+
def center(first = nil, **kwargs)
|
|
185
|
+
Widgets::Center.coerce_args(first, kwargs)
|
|
176
186
|
end
|
|
177
187
|
|
|
178
188
|
# Creates a Widgets::RatatuiLogo.
|
|
179
189
|
# @return [Widgets::RatatuiLogo]
|
|
180
|
-
def ratatui_logo(
|
|
181
|
-
Widgets::RatatuiLogo.
|
|
190
|
+
def ratatui_logo(first = nil, **kwargs)
|
|
191
|
+
Widgets::RatatuiLogo.coerce_args(first, kwargs)
|
|
182
192
|
end
|
|
183
193
|
|
|
184
194
|
# Creates a Widgets::RatatuiMascot.
|
|
185
195
|
# @return [Widgets::RatatuiMascot]
|
|
186
|
-
def ratatui_mascot(
|
|
187
|
-
Widgets::RatatuiMascot.
|
|
196
|
+
def ratatui_mascot(first = nil, **kwargs)
|
|
197
|
+
Widgets::RatatuiMascot.coerce_args(first, kwargs)
|
|
188
198
|
end
|
|
189
199
|
|
|
190
200
|
# Creates a Widgets::Shape::Label.
|
|
191
201
|
# @return [Widgets::Shape::Label]
|
|
192
|
-
def shape_label(
|
|
193
|
-
Widgets::Shape::Label.
|
|
202
|
+
def shape_label(first = nil, **kwargs)
|
|
203
|
+
Widgets::Shape::Label.coerce_args(first, kwargs)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# =====================================
|
|
207
|
+
# Widget Dispatcher (TIMTOWTDI)
|
|
208
|
+
# =====================================
|
|
209
|
+
|
|
210
|
+
# Creates a widget by type symbol.
|
|
211
|
+
#
|
|
212
|
+
# Plugin systems and config-driven UIs need to instantiate widgets by name.
|
|
213
|
+
# Without a dispatcher, you need tedious case statements or reflection.
|
|
214
|
+
#
|
|
215
|
+
# This method routes widget creation through a single entry point.
|
|
216
|
+
# Pass the type as a symbol and the remaining parameters as kwargs.
|
|
217
|
+
#
|
|
218
|
+
# Use it for dynamic UI generation, dashboard builders, or plugin architectures.
|
|
219
|
+
#
|
|
220
|
+
# Also available as: <tt>tui.paragraph</tt>, <tt>tui.list</tt>, etc.
|
|
221
|
+
#
|
|
222
|
+
# === Examples
|
|
223
|
+
#
|
|
224
|
+
#--
|
|
225
|
+
# SPDX-SnippetBegin
|
|
226
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
227
|
+
# SPDX-License-Identifier: MIT-0
|
|
228
|
+
#++
|
|
229
|
+
# tui.widget(:paragraph, text: "Hello World")
|
|
230
|
+
# tui.widget(:list, items: %w[One Two Three])
|
|
231
|
+
#
|
|
232
|
+
# # Config-driven widget creation
|
|
233
|
+
# widgets_config.each do |cfg|
|
|
234
|
+
# frame.render_widget(tui.widget(cfg[:type], **cfg[:options]), area)
|
|
235
|
+
# end
|
|
236
|
+
#--
|
|
237
|
+
# SPDX-SnippetEnd
|
|
238
|
+
#++
|
|
239
|
+
#
|
|
240
|
+
# @param type [Symbol] Widget type (see error message for full list)
|
|
241
|
+
# @return [Widgets::*]
|
|
242
|
+
def widget(type, first = nil, **)
|
|
243
|
+
case type
|
|
244
|
+
when :block then block(first, **)
|
|
245
|
+
when :paragraph then paragraph(first, **)
|
|
246
|
+
when :list then list(first, **)
|
|
247
|
+
when :table then table(first, **)
|
|
248
|
+
when :tabs then tabs(first, **)
|
|
249
|
+
when :gauge then gauge(first, **)
|
|
250
|
+
when :line_gauge then line_gauge(first, **)
|
|
251
|
+
when :sparkline then sparkline(first, **)
|
|
252
|
+
when :bar_chart then bar_chart(first, **)
|
|
253
|
+
when :chart then chart(first, **)
|
|
254
|
+
when :scrollbar then scrollbar(first, **)
|
|
255
|
+
when :calendar then calendar(first, **)
|
|
256
|
+
when :canvas then canvas(first, **)
|
|
257
|
+
when :clear then clear(first, **)
|
|
258
|
+
when :cursor then cursor(first, **)
|
|
259
|
+
when :overlay then overlay(first, **)
|
|
260
|
+
when :center then center(first, **)
|
|
261
|
+
when :ratatui_logo then ratatui_logo(first, **)
|
|
262
|
+
when :ratatui_mascot then ratatui_mascot(first, **)
|
|
263
|
+
else
|
|
264
|
+
raise ArgumentError, "Unknown widget type: #{type.inspect}. " \
|
|
265
|
+
"Valid types: :block, :paragraph, :list, :table, :tabs, :gauge, :line_gauge, " \
|
|
266
|
+
":sparkline, :bar_chart, :chart, :scrollbar, :calendar, :canvas, :clear, " \
|
|
267
|
+
":cursor, :overlay, :center, :ratatui_logo, :ratatui_mascot"
|
|
268
|
+
end
|
|
194
269
|
end
|
|
195
270
|
end
|
|
196
271
|
end
|
data/lib/ratatui_ruby/tui.rb
CHANGED
|
@@ -26,6 +26,27 @@ module RatatuiRuby
|
|
|
26
26
|
#
|
|
27
27
|
# Use it within <tt>RatatuiRuby.run</tt> to build your interface cleanly.
|
|
28
28
|
#
|
|
29
|
+
# == "Do What I Mean" (DWIM) Coercion
|
|
30
|
+
#
|
|
31
|
+
# The TUI factories add a *DWIM argument coercion layer* that the underlying
|
|
32
|
+
# Widget classes don't have. This means:
|
|
33
|
+
#
|
|
34
|
+
# - <tt>tui.table(rows: [...])</tt> coerces types, normalizes arrays, etc.
|
|
35
|
+
# - <tt>RatatuiRuby::Widgets::Table.new(rows: [...])</tt> passes arguments directly
|
|
36
|
+
#--
|
|
37
|
+
# SPDX-SnippetBegin
|
|
38
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
39
|
+
# SPDX-License-Identifier: MIT-0
|
|
40
|
+
#++
|
|
41
|
+
# to Rust without coercion — invalid types will raise <tt>TypeError</tt>.
|
|
42
|
+
#
|
|
43
|
+
#--
|
|
44
|
+
# SPDX-SnippetEnd
|
|
45
|
+
#++
|
|
46
|
+
# If you bypass the factories and call <tt>Widgets::Table.new</tt> directly,
|
|
47
|
+
# you're responsible for providing correctly-typed arguments. This is useful
|
|
48
|
+
# for debugging (to trigger real Rust TypeErrors) or performance-critical code.
|
|
49
|
+
#
|
|
29
50
|
# == Thread/Ractor Safety
|
|
30
51
|
#
|
|
31
52
|
# Session is an *I/O handle*, not a data object. It has side effects (draw,
|
|
@@ -39,7 +60,7 @@ module RatatuiRuby
|
|
|
39
60
|
# [Core] Terminal operations: draw, poll_event, get_cell_at, draw_cell.
|
|
40
61
|
# [LayoutFactories] Layout helpers: rect, constraint_*, layout, layout_split.
|
|
41
62
|
# [StyleFactories] Style helpers: style.
|
|
42
|
-
# [WidgetFactories] Widget creation: block, paragraph, list, table, etc.
|
|
63
|
+
# [WidgetFactories] Widget creation: block, paragraph, list, table, etc. (DWIM coercion)
|
|
43
64
|
# [TextFactories] Text helpers: span, line, text_width.
|
|
44
65
|
# [StateFactories] State objects: list_state, table_state, scrollbar_state.
|
|
45
66
|
# [CanvasFactories] Canvas shapes: shape_map, shape_line, shape_point, etc.
|
data/lib/ratatui_ruby/version.rb
CHANGED
|
@@ -14,6 +14,8 @@ module RatatuiRuby
|
|
|
14
14
|
#
|
|
15
15
|
# BarChart::Bar.new(value: 10, style: Style.new(fg: :red), label: "A")
|
|
16
16
|
class Bar < Data.define(:value, :label, :style, :value_style, :text_value)
|
|
17
|
+
include CoerceableWidget
|
|
18
|
+
|
|
17
19
|
##
|
|
18
20
|
# :attr_reader: value
|
|
19
21
|
# The value of the bar (Integer).
|
|
@@ -14,6 +14,8 @@ module RatatuiRuby
|
|
|
14
14
|
#
|
|
15
15
|
# BarChart::BarGroup.new(label: "Q1", bars: [BarChart::Bar.new(value: 10), BarChart::Bar.new(value: 20)])
|
|
16
16
|
class BarGroup < Data.define(:label, :bars)
|
|
17
|
+
include CoerceableWidget
|
|
18
|
+
|
|
17
19
|
##
|
|
18
20
|
# :attr_reader: label
|
|
19
21
|
# The label of the group (String).
|
|
@@ -41,6 +41,8 @@ module RatatuiRuby
|
|
|
41
41
|
# SPDX-SnippetEnd
|
|
42
42
|
#++
|
|
43
43
|
class BarChart < Data.define(:data, :bar_width, :bar_gap, :group_gap, :max, :style, :block, :direction, :label_style, :value_style, :bar_set)
|
|
44
|
+
include CoerceableWidget
|
|
45
|
+
|
|
44
46
|
##
|
|
45
47
|
##
|
|
46
48
|
##
|
|
@@ -215,19 +217,25 @@ module RatatuiRuby
|
|
|
215
217
|
# SPDX-SnippetEnd
|
|
216
218
|
#++
|
|
217
219
|
def initialize(data:, bar_width: 3, bar_gap: 1, group_gap: 0, max: nil, style: nil, block: nil, direction: :vertical, label_style: nil, value_style: nil, bar_set: nil)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
220
|
+
# Normalize bar_set to Hash[Symbol, String] if provided as Array or Hash
|
|
221
|
+
bar_set = case bar_set
|
|
222
|
+
when Symbol, nil
|
|
223
|
+
bar_set
|
|
224
|
+
when Array
|
|
225
|
+
# Convert Array to Hash using BAR_KEYS order
|
|
226
|
+
BAR_KEYS.zip(bar_set).to_h
|
|
227
|
+
when Hash
|
|
228
|
+
# @type var raw_hash: Hash[untyped, untyped]
|
|
229
|
+
raw_hash = bar_set.dup
|
|
230
|
+
normalized = {} #: Hash[Symbol, String]
|
|
231
|
+
# Normalize numeric keys (0-8) to symbolic keys
|
|
232
|
+
BAR_KEYS.each_with_index do |key, i|
|
|
233
|
+
val = raw_hash.delete(i) || raw_hash.delete(i.to_s) || raw_hash.delete(key)
|
|
234
|
+
normalized[key] = val.to_s if val
|
|
235
|
+
end
|
|
236
|
+
normalized
|
|
237
|
+
else
|
|
238
|
+
bar_set
|
|
231
239
|
end
|
|
232
240
|
|
|
233
241
|
# Normalize data to Array of BarGroup
|
|
@@ -248,12 +256,13 @@ module RatatuiRuby
|
|
|
248
256
|
elsif data.first.is_a?(BarGroup)
|
|
249
257
|
data
|
|
250
258
|
elsif data.first.is_a?(Array)
|
|
251
|
-
# Tuples
|
|
259
|
+
# Tuples - use type assertion for Steep
|
|
252
260
|
if direction == :horizontal
|
|
253
261
|
bars = data.map do |item|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
262
|
+
tuple = item #: Array[untyped]
|
|
263
|
+
label = tuple[0].to_s
|
|
264
|
+
value = tuple[1]
|
|
265
|
+
style = tuple[2]
|
|
257
266
|
|
|
258
267
|
bar = Bar.new(value:, label:)
|
|
259
268
|
bar = bar.with(style:) if style
|
|
@@ -262,9 +271,10 @@ module RatatuiRuby
|
|
|
262
271
|
[BarGroup.new(label: "", bars:)]
|
|
263
272
|
else
|
|
264
273
|
data.map do |item|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
274
|
+
tuple = item #: Array[untyped]
|
|
275
|
+
label = tuple[0].to_s
|
|
276
|
+
value = tuple[1]
|
|
277
|
+
style = tuple[2]
|
|
268
278
|
|
|
269
279
|
bar = Bar.new(value:)
|
|
270
280
|
bar = bar.with(style:) if style
|
|
@@ -23,6 +23,8 @@ module RatatuiRuby
|
|
|
23
23
|
#
|
|
24
24
|
# ruby examples/widget_box/app.rb
|
|
25
25
|
class Block < Data.define(:title, :titles, :title_alignment, :title_style, :borders, :border_style, :border_type, :border_set, :style, :padding, :children)
|
|
26
|
+
include CoerceableWidget
|
|
27
|
+
|
|
26
28
|
##
|
|
27
29
|
# :attr_reader: title
|
|
28
30
|
# The main title displayed on the top border.
|
|
@@ -170,8 +172,8 @@ module RatatuiRuby
|
|
|
170
172
|
if border_set
|
|
171
173
|
border_set = border_set.dup
|
|
172
174
|
%i[top_left top_right bottom_left bottom_right vertical_left vertical_right horizontal_top horizontal_bottom].each do |long_key|
|
|
173
|
-
short_key = long_key.to_s.split("_").map { |s| s[0] }.join
|
|
174
|
-
if (val = border_set.delete(short_key
|
|
175
|
+
short_key = long_key.to_s.split("_").map { |s| s[0] }.join.to_sym
|
|
176
|
+
if (val = border_set.delete(short_key))
|
|
175
177
|
border_set[long_key] = val
|
|
176
178
|
end
|
|
177
179
|
end
|
|
@@ -237,12 +239,18 @@ module RatatuiRuby
|
|
|
237
239
|
top_border = has_border.call(:top) ? 1 : 0
|
|
238
240
|
bottom_border = has_border.call(:bottom) ? 1 : 0
|
|
239
241
|
|
|
240
|
-
# Calculate padding offsets
|
|
241
|
-
if padding.is_a?(Array)
|
|
242
|
+
# Calculate padding offsets - ensure all are Integer
|
|
243
|
+
pad_left, pad_right, pad_top, pad_bottom = if padding.is_a?(Array)
|
|
242
244
|
# [left, right, top, bottom]
|
|
243
|
-
|
|
245
|
+
[
|
|
246
|
+
Integer(padding[0] || 0),
|
|
247
|
+
Integer(padding[1] || 0),
|
|
248
|
+
Integer(padding[2] || 0),
|
|
249
|
+
Integer(padding[3] || 0),
|
|
250
|
+
]
|
|
244
251
|
else
|
|
245
|
-
|
|
252
|
+
p = Integer(padding)
|
|
253
|
+
[p, p, p, p]
|
|
246
254
|
end
|
|
247
255
|
|
|
248
256
|
# Compute inner area
|
|
@@ -24,6 +24,8 @@ module RatatuiRuby
|
|
|
24
24
|
#
|
|
25
25
|
# ruby examples/widget_calendar/app.rb
|
|
26
26
|
class Calendar < Data.define(:year, :month, :events, :default_style, :header_style, :block, :show_weekdays_header, :show_surrounding, :show_month_header)
|
|
27
|
+
include CoerceableWidget
|
|
28
|
+
|
|
27
29
|
##
|
|
28
30
|
# :attr_reader: year
|
|
29
31
|
# The year to display (Integer).
|