ruflet 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/bin/ruflet +6 -0
  3. data/lib/ruflet/cli/build_command.rb +372 -0
  4. data/lib/ruflet/cli/extra_command.rb +146 -0
  5. data/lib/ruflet/cli/flutter_sdk.rb +359 -0
  6. data/lib/ruflet/cli/new_command.rb +221 -0
  7. data/lib/ruflet/cli/run_command.rb +699 -0
  8. data/lib/ruflet/cli/templates.rb +68 -0
  9. data/lib/ruflet/cli/update_command.rb +111 -0
  10. data/lib/ruflet/cli.rb +85 -0
  11. data/lib/ruflet/version.rb +1 -1
  12. data/lib/ruflet_cli.rb +3 -0
  13. metadata +59 -75
  14. data/lib/ruflet/manifest_compiler.rb +0 -62
  15. data/lib/ruflet.rb +0 -40
  16. data/lib/ruflet_protocol/ruflet/protocol.rb +0 -62
  17. data/lib/ruflet_protocol.rb +0 -4
  18. data/lib/ruflet_ui/ruflet/app.rb +0 -31
  19. data/lib/ruflet_ui/ruflet/colors.rb +0 -234
  20. data/lib/ruflet_ui/ruflet/control.rb +0 -168
  21. data/lib/ruflet_ui/ruflet/dsl.rb +0 -227
  22. data/lib/ruflet_ui/ruflet/event.rb +0 -28
  23. data/lib/ruflet_ui/ruflet/icon_data.rb +0 -62
  24. data/lib/ruflet_ui/ruflet/icons/cupertino/cupertino_icons.rb +0 -54
  25. data/lib/ruflet_ui/ruflet/icons/cupertino_icon_lookup.rb +0 -112
  26. data/lib/ruflet_ui/ruflet/icons/material_icon_lookup.rb +0 -112
  27. data/lib/ruflet_ui/ruflet/icons/material_icons.rb +0 -55
  28. data/lib/ruflet_ui/ruflet/page.rb +0 -741
  29. data/lib/ruflet_ui/ruflet/ui/control_factory.rb +0 -23
  30. data/lib/ruflet_ui/ruflet/ui/control_methods.rb +0 -16
  31. data/lib/ruflet_ui/ruflet/ui/control_registry.rb +0 -13
  32. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_action_sheet_control.rb +0 -13
  33. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_alert_dialog_control.rb +0 -13
  34. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_button_control.rb +0 -13
  35. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_dialog_action_control.rb +0 -24
  36. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_filled_button_control.rb +0 -13
  37. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_navigation_bar_control.rb +0 -13
  38. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_slider_control.rb +0 -13
  39. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_switch_control.rb +0 -13
  40. data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_text_field_control.rb +0 -13
  41. data/lib/ruflet_ui/ruflet/ui/controls/material/alert_dialog_control.rb +0 -13
  42. data/lib/ruflet_ui/ruflet/ui/controls/material/app_bar_control.rb +0 -13
  43. data/lib/ruflet_ui/ruflet/ui/controls/material/bottom_sheet_control.rb +0 -13
  44. data/lib/ruflet_ui/ruflet/ui/controls/material/button_control.rb +0 -24
  45. data/lib/ruflet_ui/ruflet/ui/controls/material/checkbox_control.rb +0 -13
  46. data/lib/ruflet_ui/ruflet/ui/controls/material/column_control.rb +0 -13
  47. data/lib/ruflet_ui/ruflet/ui/controls/material/container_control.rb +0 -13
  48. data/lib/ruflet_ui/ruflet/ui/controls/material/drag_target_control.rb +0 -13
  49. data/lib/ruflet_ui/ruflet/ui/controls/material/draggable_control.rb +0 -13
  50. data/lib/ruflet_ui/ruflet/ui/controls/material/elevated_button_control.rb +0 -13
  51. data/lib/ruflet_ui/ruflet/ui/controls/material/filled_button_control.rb +0 -13
  52. data/lib/ruflet_ui/ruflet/ui/controls/material/floating_action_button_control.rb +0 -28
  53. data/lib/ruflet_ui/ruflet/ui/controls/material/gesture_detector_control.rb +0 -13
  54. data/lib/ruflet_ui/ruflet/ui/controls/material/grid_view_control.rb +0 -13
  55. data/lib/ruflet_ui/ruflet/ui/controls/material/icon_button_control.rb +0 -13
  56. data/lib/ruflet_ui/ruflet/ui/controls/material/icon_control.rb +0 -24
  57. data/lib/ruflet_ui/ruflet/ui/controls/material/image_control.rb +0 -13
  58. data/lib/ruflet_ui/ruflet/ui/controls/material/markdown_control.rb +0 -13
  59. data/lib/ruflet_ui/ruflet/ui/controls/material/navigation_bar_control.rb +0 -13
  60. data/lib/ruflet_ui/ruflet/ui/controls/material/navigation_bar_destination_control.rb +0 -13
  61. data/lib/ruflet_ui/ruflet/ui/controls/material/radio_control.rb +0 -13
  62. data/lib/ruflet_ui/ruflet/ui/controls/material/radio_group_control.rb +0 -13
  63. data/lib/ruflet_ui/ruflet/ui/controls/material/row_control.rb +0 -13
  64. data/lib/ruflet_ui/ruflet/ui/controls/material/snack_bar_control.rb +0 -68
  65. data/lib/ruflet_ui/ruflet/ui/controls/material/stack_control.rb +0 -13
  66. data/lib/ruflet_ui/ruflet/ui/controls/material/tab_bar_control.rb +0 -13
  67. data/lib/ruflet_ui/ruflet/ui/controls/material/tab_bar_view_control.rb +0 -13
  68. data/lib/ruflet_ui/ruflet/ui/controls/material/tab_control.rb +0 -13
  69. data/lib/ruflet_ui/ruflet/ui/controls/material/tabs_control.rb +0 -63
  70. data/lib/ruflet_ui/ruflet/ui/controls/material/text_button_control.rb +0 -13
  71. data/lib/ruflet_ui/ruflet/ui/controls/material/text_control.rb +0 -13
  72. data/lib/ruflet_ui/ruflet/ui/controls/material/text_field_control.rb +0 -13
  73. data/lib/ruflet_ui/ruflet/ui/controls/material/view_control.rb +0 -13
  74. data/lib/ruflet_ui/ruflet/ui/cupertino_control_factory.rb +0 -40
  75. data/lib/ruflet_ui/ruflet/ui/cupertino_control_methods.rb +0 -26
  76. data/lib/ruflet_ui/ruflet/ui/cupertino_control_registry.rb +0 -49
  77. data/lib/ruflet_ui/ruflet/ui/material_control_factory.rb +0 -97
  78. data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +0 -128
  79. data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +0 -154
  80. data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +0 -89
  81. data/lib/ruflet_ui/ruflet/ui/widget_builder.rb +0 -55
  82. data/lib/ruflet_ui.rb +0 -111
@@ -1,234 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Ruflet
4
- module Colors
5
- SEMANTIC_COLORS = {
6
- PRIMARY: "primary",
7
- ON_PRIMARY: "onprimary",
8
- PRIMARY_CONTAINER: "primarycontainer",
9
- ON_PRIMARY_CONTAINER: "onprimarycontainer",
10
- PRIMARY_FIXED: "primaryfixed",
11
- PRIMARY_FIXED_DIM: "primaryfixeddim",
12
- ON_PRIMARY_FIXED: "onprimaryfixed",
13
- ON_PRIMARY_FIXED_VARIANT: "onprimaryfixedvariant",
14
- SECONDARY: "secondary",
15
- ON_SECONDARY: "onsecondary",
16
- SECONDARY_CONTAINER: "secondarycontainer",
17
- ON_SECONDARY_CONTAINER: "onsecondarycontainer",
18
- SECONDARY_FIXED: "secondaryfixed",
19
- SECONDARY_FIXED_DIM: "secondaryfixeddim",
20
- ON_SECONDARY_FIXED: "onsecondaryfixed",
21
- ON_SECONDARY_FIXED_VARIANT: "onsecondaryfixedvariant",
22
- TERTIARY: "tertiary",
23
- ON_TERTIARY: "ontertiary",
24
- TERTIARY_CONTAINER: "tertiarycontainer",
25
- ON_TERTIARY_CONTAINER: "ontertiarycontainer",
26
- TERTIARY_FIXED: "tertiaryfixed",
27
- TERTIARY_FIXED_DIM: "tertiaryfixeddim",
28
- ON_TERTIARY_FIXED: "ontertiaryfixed",
29
- ON_TERTIARY_FIXED_VARIANT: "ontertiaryfixedvariant",
30
- ERROR: "error",
31
- ON_ERROR: "onerror",
32
- ERROR_CONTAINER: "errorcontainer",
33
- ON_ERROR_CONTAINER: "onerrorcontainer",
34
- SURFACE: "surface",
35
- ON_SURFACE: "onsurface",
36
- ON_SURFACE_VARIANT: "onsurfacevariant",
37
- SURFACE_TINT: "surfacetint",
38
- SURFACE_DIM: "surfacedim",
39
- SURFACE_BRIGHT: "surfacebright",
40
- SURFACE_CONTAINER: "surfacecontainer",
41
- SURFACE_CONTAINER_LOW: "surfacecontainerlow",
42
- SURFACE_CONTAINER_LOWEST: "surfacecontainerlowest",
43
- SURFACE_CONTAINER_HIGH: "surfacecontainerhigh",
44
- SURFACE_CONTAINER_HIGHEST: "surfacecontainerhighest",
45
- OUTLINE: "outline",
46
- OUTLINE_VARIANT: "outlinevariant",
47
- SHADOW: "shadow",
48
- SCRIM: "scrim",
49
- INVERSE_SURFACE: "inversesurface",
50
- ON_INVERSE_SURFACE: "oninversesurface",
51
- INVERSE_PRIMARY: "inverseprimary"
52
- }.freeze
53
-
54
- BASE_PRIMARY = %w[
55
- amber blue bluegrey brown cyan deeporange deeppurple green grey indigo lightblue
56
- lightgreen lime orange pink purple red teal yellow
57
- ].freeze
58
- BASE_ACCENT = %w[
59
- amber blue cyan deeporange deeppurple green indigo lightblue lightgreen lime
60
- orange pink purple red teal yellow
61
- ].freeze
62
- PRIMARY_SHADES = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900].freeze
63
- ACCENT_SHADES = [100, 200, 400, 700].freeze
64
-
65
- FIXED_COLORS = {
66
- BLACK: "black",
67
- BLACK_12: "black12",
68
- BLACK_26: "black26",
69
- BLACK_38: "black38",
70
- BLACK_45: "black45",
71
- BLACK_54: "black54",
72
- BLACK_87: "black87",
73
- WHITE: "white",
74
- WHITE_10: "white10",
75
- WHITE_12: "white12",
76
- WHITE_24: "white24",
77
- WHITE_30: "white30",
78
- WHITE_38: "white38",
79
- WHITE_54: "white54",
80
- WHITE_60: "white60",
81
- WHITE_70: "white70",
82
- TRANSPARENT: "transparent"
83
- }.freeze
84
-
85
- DEPRECATED_ALIASES = {
86
- BLACK12: :BLACK_12,
87
- BLACK26: :BLACK_26,
88
- BLACK38: :BLACK_38,
89
- BLACK45: :BLACK_45,
90
- BLACK54: :BLACK_54,
91
- BLACK87: :BLACK_87,
92
- WHITE10: :WHITE_10,
93
- WHITE12: :WHITE_12,
94
- WHITE24: :WHITE_24,
95
- WHITE30: :WHITE_30,
96
- WHITE38: :WHITE_38,
97
- WHITE54: :WHITE_54,
98
- WHITE60: :WHITE_60,
99
- WHITE70: :WHITE_70
100
- }.freeze
101
-
102
- def with_opacity(opacity, color)
103
- value = Float(opacity)
104
- raise ArgumentError, "opacity must be between 0.0 and 1.0 inclusive, got #{opacity}" unless value.between?(0.0, 1.0)
105
-
106
- "#{normalize_color(color)},#{value}"
107
- end
108
-
109
- def random(exclude: nil, weights: nil)
110
- choices = all_values.dup
111
- excluded = Array(exclude).map { |c| normalize_color(c) }
112
- choices.reject! { |c| excluded.include?(c) }
113
- return nil if choices.empty?
114
-
115
- if weights && !weights.empty?
116
- expanded = choices.flat_map do |color|
117
- weight = weights.fetch(color, weights.fetch(color.to_sym, 1)).to_i rescue 1
118
- weight = 1 if weight <= 0
119
- [color] * weight
120
- end
121
- return expanded.sample
122
- end
123
-
124
- choices.sample
125
- end
126
-
127
- def all_values
128
- return @all_values if @all_values
129
-
130
- values = []
131
- SEMANTIC_COLORS.each_value { |v| values << v }
132
- FIXED_COLORS.each_value { |v| values << v }
133
-
134
- BASE_PRIMARY.each do |base|
135
- values << base
136
- PRIMARY_SHADES.each do |shade|
137
- values << "#{base}#{shade}"
138
- end
139
- end
140
-
141
- BASE_ACCENT.each do |base|
142
- values << "#{base}accent"
143
- ACCENT_SHADES.each do |shade|
144
- values << "#{base}accent#{shade}"
145
- end
146
- end
147
-
148
- uniq_map = {}
149
- values.each { |v| uniq_map[v] = true }
150
- @all_values = uniq_map.keys.freeze
151
- end
152
-
153
- def self.normalize_color(color)
154
- return color.to_s if color.is_a?(Symbol)
155
- return color if color.is_a?(String)
156
- return color.to_s unless color.respond_to?(:to_s)
157
-
158
- color.to_s
159
- end
160
-
161
- BASE_PREFIX = {
162
- "amber" => "AMBER",
163
- "blue" => "BLUE",
164
- "bluegrey" => "BLUE_GREY",
165
- "brown" => "BROWN",
166
- "cyan" => "CYAN",
167
- "deeporange" => "DEEP_ORANGE",
168
- "deeppurple" => "DEEP_PURPLE",
169
- "green" => "GREEN",
170
- "grey" => "GREY",
171
- "indigo" => "INDIGO",
172
- "lightblue" => "LIGHT_BLUE",
173
- "lightgreen" => "LIGHT_GREEN",
174
- "lime" => "LIME",
175
- "orange" => "ORANGE",
176
- "pink" => "PINK",
177
- "purple" => "PURPLE",
178
- "red" => "RED",
179
- "teal" => "TEAL",
180
- "yellow" => "YELLOW"
181
- }.freeze
182
-
183
- def self.constant_prefix_for(base_name)
184
- key = base_name.to_s
185
- return BASE_PREFIX[key] if BASE_PREFIX.key?(key)
186
- key.upcase
187
- end
188
-
189
- SEMANTIC_COLORS.each { |k, v| const_set(k, v) }
190
- FIXED_COLORS.each { |k, v| const_set(k, v) }
191
-
192
- BASE_PRIMARY.each do |base|
193
- prefix = self.constant_prefix_for(base)
194
- const_set(prefix, base)
195
- PRIMARY_SHADES.each do |shade|
196
- const_set("#{prefix}_#{shade}", "#{base}#{shade}")
197
- end
198
- end
199
-
200
- BASE_ACCENT.each do |base|
201
- prefix = "#{self.constant_prefix_for(base)}_ACCENT"
202
- const_set(prefix, "#{base}accent")
203
- ACCENT_SHADES.each do |shade|
204
- const_set("#{prefix}_#{shade}", "#{base}accent#{shade}")
205
- end
206
- end
207
-
208
- DEPRECATED_ALIASES.each do |alias_name, target|
209
- const_set(alias_name, const_get(target))
210
- end
211
-
212
- constant_names = []
213
- SEMANTIC_COLORS.each_key { |k| constant_names << k }
214
- FIXED_COLORS.each_key { |k| constant_names << k }
215
- BASE_PRIMARY.each do |base|
216
- constant_names << constant_prefix_for(base).to_sym
217
- PRIMARY_SHADES.each { |shade| constant_names << "#{constant_prefix_for(base)}_#{shade}".to_sym }
218
- end
219
- BASE_ACCENT.each do |base|
220
- constant_names << "#{constant_prefix_for(base)}_ACCENT".to_sym
221
- ACCENT_SHADES.each { |shade| constant_names << "#{constant_prefix_for(base)}_ACCENT_#{shade}".to_sym }
222
- end
223
- DEPRECATED_ALIASES.each_key { |k| constant_names << k }
224
-
225
- uniq_constants = {}
226
- constant_names.each { |n| uniq_constants[n] = true }
227
- if respond_to?(:define_singleton_method)
228
- uniq_constants.keys.each do |name|
229
- next if respond_to?(name)
230
- define_singleton_method(name) { const_get(name) }
231
- end
232
- end
233
- end
234
- end
@@ -1,168 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- begin
4
- require "securerandom"
5
- rescue LoadError
6
- nil
7
- end
8
- require_relative "ui/control_registry"
9
- require_relative "icon_data"
10
- require_relative "icons/material_icon_lookup"
11
- require_relative "icons/cupertino_icon_lookup"
12
-
13
- module Ruflet
14
- class Control
15
- TYPE_MAP = UI::ControlRegistry::TYPE_MAP
16
- EVENT_PROPS = UI::ControlRegistry::EVENT_PROPS
17
- HOST_EXPANDED_TYPES = %w[view row column].freeze
18
-
19
- attr_reader :type, :id, :props, :children
20
- attr_accessor :wire_id, :runtime_page
21
-
22
- def initialize(type:, id: nil, **props)
23
- @type = type.to_s.downcase
24
- @id = (id || props.delete(:id) || "ctrl_#{self.class.generate_id}").to_s
25
- @children = []
26
- @handlers = {}
27
- @wire_id = nil
28
- @props = normalize_props(extract_handlers(preprocess_props(props)))
29
- end
30
-
31
- def on(event_name, &block)
32
- name = normalized_event_name(event_name)
33
- @handlers[name] = block
34
- @props["on_#{name}"] = true
35
- runtime_page&.update(self, "on_#{name}": true) if wire_id
36
- self
37
- end
38
-
39
- def emit(event_name, event)
40
- handler = @handlers[normalized_event_name(event_name)]
41
- return false unless handler
42
-
43
- handler.call(event)
44
- true
45
- end
46
-
47
- def has_handler?(event_name)
48
- @handlers.key?(normalized_event_name(event_name))
49
- end
50
-
51
- def to_patch
52
- patch = {
53
- "_c" => TYPE_MAP.fetch(type, type.split("_").map(&:capitalize).join),
54
- "_i" => wire_id
55
- }
56
-
57
- internals = {}
58
- internals["host_positioned"] = true if type == "stack"
59
- internals["host_expanded"] = true if HOST_EXPANDED_TYPES.include?(type)
60
- patch["_internals"] = internals unless internals.empty?
61
-
62
- props.each { |k, v| patch[k] = serialize_value(v) }
63
- patch["controls"] = children.map(&:to_patch) unless children.empty?
64
- patch
65
- end
66
-
67
- private
68
-
69
- class << self
70
- def generate_id
71
- if defined?(SecureRandom) && SecureRandom.respond_to?(:hex)
72
- SecureRandom.hex(4)
73
- else
74
- format("%08x", rand(0..0xffff_ffff))
75
- end
76
- end
77
- end
78
-
79
- def serialize_value(value)
80
- case value
81
- when Control
82
- value.to_patch
83
- when Ruflet::IconData
84
- value.value
85
- when Array
86
- value.map { |v| serialize_value(v) }
87
- when Hash
88
- value.transform_values { |v| serialize_value(v) }
89
- else
90
- value
91
- end
92
- end
93
-
94
- def extract_handlers(input)
95
- output = input.dup
96
-
97
- EVENT_PROPS.each do |prop, event_name|
98
- string_prop = prop.to_s
99
- next unless output.key?(prop) || output.key?(string_prop)
100
-
101
- handler = output.key?(prop) ? output.delete(prop) : output.delete(string_prop)
102
- @handlers[event_name] = handler if handler.respond_to?(:call)
103
- output["on_#{event_name}"] = true
104
- end
105
-
106
- output
107
- end
108
-
109
- def normalize_props(hash)
110
- hash.each_with_object({}) do |(k, v), result|
111
- key = k.to_s
112
- mapped_key = key
113
- value =
114
- if v.is_a?(Symbol)
115
- v.to_s
116
- elsif v.is_a?(Ruflet::IconData)
117
- v.value
118
- else
119
- v
120
- end
121
- value = normalize_icon_prop(mapped_key, value)
122
- value = normalize_color_prop(mapped_key, value)
123
-
124
- result[mapped_key] = value
125
- end
126
- end
127
-
128
- def preprocess_props(props)
129
- props
130
- end
131
-
132
- def normalize_color_prop(key, value)
133
- return value unless value.is_a?(String)
134
- return value.downcase if color_prop_key?(key)
135
-
136
- value
137
- end
138
-
139
- def color_prop_key?(key)
140
- key == "color" || key == "bgcolor" || key.end_with?("_color")
141
- end
142
-
143
- def normalize_icon_prop(key, value)
144
- return value unless icon_prop_key?(key)
145
- codepoint = resolve_icon_codepoint(value)
146
- codepoint.nil? ? value : codepoint
147
- end
148
-
149
- def icon_prop_key?(key)
150
- key == "icon" || key.end_with?("_icon")
151
- end
152
-
153
- def resolve_icon_codepoint(value)
154
- return nil unless value.is_a?(Integer) || value.is_a?(Symbol) || value.is_a?(String)
155
-
156
- codepoint = Ruflet::MaterialIconLookup.codepoint_for(value)
157
- if codepoint.nil? || (value.is_a?(Integer) && codepoint == value)
158
- cupertino = Ruflet::CupertinoIconLookup.codepoint_for(value)
159
- codepoint = cupertino unless cupertino.nil?
160
- end
161
- codepoint
162
- end
163
-
164
- def normalized_event_name(event_name)
165
- event_name.to_s.sub(/\Aon_/, "")
166
- end
167
- end
168
- end
@@ -1,227 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "ui/control_methods"
4
- require_relative "ui/control_factory"
5
-
6
- module Ruflet
7
- module DSL
8
- DURATION_FACTORS_MS = {
9
- days: 86_400_000.0,
10
- hours: 3_600_000.0,
11
- minutes: 60_000.0,
12
- seconds: 1_000.0,
13
- milliseconds: 1.0,
14
- microseconds: 0.001
15
- }.freeze
16
-
17
- module_function
18
-
19
- def _pending_app
20
- @_pending_app ||= App.new(host: "0.0.0.0", port: 8550)
21
- end
22
-
23
- def _reset_pending_app!
24
- @_pending_app = App.new(host: "0.0.0.0", port: 8550)
25
- end
26
-
27
- def app(host: "0.0.0.0", port: 8550, &block)
28
- return App.new(host: host, port: port).tap { |a| a.instance_eval(&block) } if block
29
-
30
- pending = _pending_app
31
- pending.set_endpoint!(host: host, port: port)
32
- _reset_pending_app!
33
- pending
34
- end
35
-
36
- def page(**props, &block) = _pending_app.page(**props, &block)
37
- def control(type, **props, &block) = _pending_app.control(type, **props, &block)
38
- def widget(type, **props, &block) = _pending_app.widget(type, **props, &block)
39
- def column(**props, &block) = _pending_app.column(**props, &block)
40
- def center(**props, &block) = _pending_app.center(**props, &block)
41
- def row(**props, &block) = _pending_app.row(**props, &block)
42
- def stack(**props, &block) = _pending_app.stack(**props, &block)
43
- def grid_view(**props, &block) = _pending_app.grid_view(**props, &block)
44
- def gridview(**props, &block) = _pending_app.gridview(**props, &block)
45
- def container(**props, &block) = _pending_app.container(**props, &block)
46
- def gesture_detector(**props, &block) = _pending_app.gesture_detector(**props, &block)
47
- def gesturedetector(**props, &block) = _pending_app.gesturedetector(**props, &block)
48
- def draggable(**props, &block) = _pending_app.draggable(**props, &block)
49
- def drag_target(**props, &block) = _pending_app.drag_target(**props, &block)
50
- def dragtarget(**props, &block) = _pending_app.dragtarget(**props, &block)
51
- def text(value = nil, **props) = _pending_app.text(value, **props)
52
- def button(**props) = _pending_app.button(**props)
53
- def elevated_button(**props) = _pending_app.elevated_button(**props)
54
- def elevatedbutton(**props) = _pending_app.elevatedbutton(**props)
55
- def text_field(**props) = _pending_app.text_field(**props)
56
- def textfield(**props) = _pending_app.textfield(**props)
57
- def icon(**props) = _pending_app.icon(**props)
58
- def image(src = nil, **props) = _pending_app.image(src, **props)
59
- def icon_button(**props) = _pending_app.icon_button(**props)
60
- def iconbutton(**props) = _pending_app.iconbutton(**props)
61
- def app_bar(**props) = _pending_app.app_bar(**props)
62
- def appbar(**props) = _pending_app.appbar(**props)
63
- def clipboard(**props) = _pending_app.clipboard(**props)
64
- def text_button(**props) = _pending_app.text_button(**props)
65
- def textbutton(**props) = _pending_app.textbutton(**props)
66
- def filled_button(**props) = _pending_app.filled_button(**props)
67
- def filledbutton(**props) = _pending_app.filledbutton(**props)
68
- def checkbox(**props) = _pending_app.checkbox(**props)
69
- def radio(**props) = _pending_app.radio(**props)
70
- def radio_group(**props) = _pending_app.radio_group(**props)
71
- def radiogroup(**props) = _pending_app.radiogroup(**props)
72
- def alert_dialog(**props) = _pending_app.alert_dialog(**props)
73
- def alertdialog(**props) = _pending_app.alertdialog(**props)
74
- def snack_bar(**props) = _pending_app.snack_bar(**props)
75
- def snackbar(**props) = _pending_app.snackbar(**props)
76
- def bottom_sheet(**props) = _pending_app.bottom_sheet(**props)
77
- def bottomsheet(**props) = _pending_app.bottomsheet(**props)
78
- def markdown(value = nil, **props) = _pending_app.markdown(value, **props)
79
- def floating_action_button(**props) = _pending_app.floating_action_button(**props)
80
- def floatingactionbutton(**props) = _pending_app.floatingactionbutton(**props)
81
- def tabs(**props, &block) = _pending_app.tabs(**props, &block)
82
- def tab(**props, &block) = _pending_app.tab(**props, &block)
83
- def tab_bar(**props, &block) = _pending_app.tab_bar(**props, &block)
84
- def tabbar(**props, &block) = _pending_app.tabbar(**props, &block)
85
- def tab_bar_view(**props, &block) = _pending_app.tab_bar_view(**props, &block)
86
- def tabbarview(**props, &block) = _pending_app.tabbarview(**props, &block)
87
- def navigation_bar(**props, &block) = _pending_app.navigation_bar(**props, &block)
88
- def navigationbar(**props, &block) = _pending_app.navigationbar(**props, &block)
89
- def navigation_bar_destination(**props, &block) = _pending_app.navigation_bar_destination(**props, &block)
90
- def navigationbardestination(**props, &block) = _pending_app.navigationbardestination(**props, &block)
91
- def fab(content = nil, **props) = _pending_app.fab(content, **props)
92
- def cupertino_button(**props) = _pending_app.cupertino_button(**props)
93
- def cupertinobutton(**props) = _pending_app.cupertinobutton(**props)
94
- def cupertino_filled_button(**props) = _pending_app.cupertino_filled_button(**props)
95
- def cupertinofilledbutton(**props) = _pending_app.cupertinofilledbutton(**props)
96
- def cupertino_text_field(**props) = _pending_app.cupertino_text_field(**props)
97
- def cupertinotextfield(**props) = _pending_app.cupertinotextfield(**props)
98
- def cupertino_switch(**props) = _pending_app.cupertino_switch(**props)
99
- def cupertinoswitch(**props) = _pending_app.cupertinoswitch(**props)
100
- def cupertino_slider(**props) = _pending_app.cupertino_slider(**props)
101
- def cupertinoslider(**props) = _pending_app.cupertinoslider(**props)
102
- def cupertino_alert_dialog(**props) = _pending_app.cupertino_alert_dialog(**props)
103
- def cupertinoalertdialog(**props) = _pending_app.cupertinoalertdialog(**props)
104
- def cupertino_action_sheet(**props) = _pending_app.cupertino_action_sheet(**props)
105
- def cupertinoactionsheet(**props) = _pending_app.cupertinoactionsheet(**props)
106
- def cupertino_dialog_action(**props) = _pending_app.cupertino_dialog_action(**props)
107
- def cupertinodialogaction(**props) = _pending_app.cupertinodialogaction(**props)
108
- def cupertino_navigation_bar(**props) = _pending_app.cupertino_navigation_bar(**props)
109
- def cupertinonavigationbar(**props) = _pending_app.cupertinonavigationbar(**props)
110
- def duration(**parts) = duration_in_milliseconds(parts)
111
-
112
- class App
113
- include UI::ControlMethods
114
-
115
- attr_reader :page_props, :host, :port
116
-
117
- def initialize(host:, port:)
118
- @host = host
119
- @port = port
120
- @roots = []
121
- @stack = []
122
- @page_props = { "route" => "/" }
123
- @seq = 0
124
- end
125
-
126
- def set_endpoint!(host:, port:)
127
- @host = host
128
- @port = port
129
- end
130
-
131
- def page(**props, &block)
132
- @page_props.merge!(normalize_props(props))
133
- instance_eval(&block) if block
134
- self
135
- end
136
-
137
- def widget(type, **props, &block)
138
- control(type.to_s, **props, &block)
139
- end
140
-
141
- def control(type, **props, &block)
142
- mapped_props = props.dup
143
- prop_children = extract_children_prop(mapped_props)
144
-
145
- id = mapped_props.delete(:id)&.to_s || next_id(type)
146
- c = Ruflet::UI::ControlFactory.build(type.to_s, id: id, **normalize_props(mapped_props))
147
- attach(c)
148
-
149
- if block
150
- @stack.push(c)
151
- instance_eval(&block)
152
- @stack.pop
153
- end
154
-
155
- if prop_children
156
- Array(prop_children).each { |child| c.children << child if child.is_a?(Ruflet::Control) }
157
- end
158
-
159
- c
160
- end
161
-
162
- def duration(**parts)
163
- DSL.duration(**parts)
164
- end
165
-
166
- def run
167
- app_roots = @roots
168
- page_props = @page_props.dup
169
-
170
- Ruflet::Server.new(host: host, port: port) do |runtime_page|
171
- runtime_page.set_view_props(page_props)
172
- runtime_page.add(*app_roots)
173
- end.start
174
- end
175
-
176
- private
177
-
178
- def build_widget(type, **props, &block) = control(type.to_s, **props, &block)
179
-
180
- def attach(control)
181
- if @stack.empty?
182
- @roots << control
183
- else
184
- @stack.last.children << control
185
- end
186
- end
187
-
188
- def normalize_props(hash)
189
- hash.transform_keys(&:to_s).transform_values { |v| v.is_a?(Symbol) ? v.to_s : v }
190
- end
191
-
192
- def extract_children_prop(props)
193
- props.delete(:children) ||
194
- props.delete("children") ||
195
- props.delete(:controls) ||
196
- props.delete("controls")
197
- end
198
-
199
- def next_id(type)
200
- @seq += 1
201
- "#{type}_#{@seq}"
202
- end
203
-
204
- def duration_in_milliseconds(parts)
205
- DSL.send(:duration_in_milliseconds, parts)
206
- end
207
-
208
- end
209
-
210
- def duration_in_milliseconds(parts)
211
- return 0 if parts.nil? || parts.empty?
212
-
213
- DURATION_FACTORS_MS.reduce(0.0) do |sum, (key, factor)|
214
- sum + read_duration_part(parts, key) * factor
215
- end.round
216
- end
217
-
218
- def read_duration_part(parts, key)
219
- raw = parts[key] || parts[key.to_s]
220
- return 0.0 if raw.nil?
221
- return raw.to_f if raw.is_a?(Numeric)
222
- return raw.to_f if raw.is_a?(String) && raw.match?(/\A-?\d+(\.\d+)?\z/)
223
-
224
- 0.0
225
- end
226
- end
227
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
-
5
- module Ruflet
6
- class Event
7
- attr_reader :name, :target, :raw_data, :data, :page, :control
8
-
9
- def initialize(name:, target:, raw_data:, page:, control:)
10
- @name = name
11
- @target = target
12
- @raw_data = raw_data
13
- @data = parse_data(raw_data)
14
- @page = page
15
- @control = control
16
- end
17
-
18
- private
19
-
20
- def parse_data(raw)
21
- return raw unless raw.is_a?(String)
22
-
23
- JSON.parse(raw)
24
- rescue JSON::ParserError
25
- raw
26
- end
27
- end
28
- end