ruflet_core 0.0.21 → 0.0.22
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/lib/ruflet/version.rb +1 -1
- data/lib/ruflet_ui/ruflet/dsl.rb +76 -0
- data/lib/ruflet_ui/ruflet/event.rb +3 -2
- data/lib/ruflet_ui/ruflet/events/gesture_events.rb +2 -1
- data/lib/ruflet_ui/ruflet/page.rb +242 -4
- data/lib/ruflet_ui/ruflet/ui/control_factory.rb +2 -0
- data/lib/ruflet_ui/ruflet/ui/control_methods.rb +4 -0
- data/lib/ruflet_ui/ruflet/ui/control_registry.rb +20 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheet_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheetaction_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactivityindicator_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoalertdialog_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoappbar_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobottomsheet_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocheckbox_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenu_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenuaction_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodatepicker_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodialogaction_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinofilledbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinolisttile_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinonavigationbar_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinopicker_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoradio_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinosegmentedbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslider_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslidingsegmentedbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoswitch_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotextfield_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotimerpicker_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotintedbutton_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/materials/ad_controls.rb +45 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/animation_extension_controls.rb +29 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/chart_controls.rb +56 -279
- data/lib/ruflet_ui/ruflet/ui/controls/materials/code_editor_control.rb +42 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/color_picker_controls.rb +34 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/datatable2_controls.rb +41 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdownm2_control.rb +1 -1
- data/lib/ruflet_ui/ruflet/ui/controls/materials/map_control.rb +80 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/ruflet_controls.rb +62 -0
- data/lib/ruflet_ui/ruflet/ui/controls/materials/video_control.rb +1 -2
- data/lib/ruflet_ui/ruflet/ui/controls/materials/webview_control.rb +5 -30
- data/lib/ruflet_ui/ruflet/ui/controls/ruflet_controls.rb +60 -0
- data/lib/ruflet_ui/ruflet/ui/controls/shared/browsercontextmenu_control.rb +17 -0
- data/lib/ruflet_ui/ruflet/ui/controls/shared/ruflet_app_control.rb +3 -3
- data/lib/ruflet_ui/ruflet/ui/controls/shared/serviceregistry_control.rb +5 -1
- data/lib/ruflet_ui/ruflet/ui/cupertino_control_methods.rb +2 -0
- data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +110 -6
- data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +23 -8
- data/lib/ruflet_ui/ruflet/ui/platform_control_contracts.rb +392 -0
- data/lib/ruflet_ui/ruflet/ui/platform_control_methods.rb +35 -0
- data/lib/ruflet_ui/ruflet/ui/services/current_service_methods.rb +220 -0
- data/lib/ruflet_ui/ruflet/ui/services/ruflet/camera_control.rb +88 -0
- data/lib/ruflet_ui/ruflet/ui/services/ruflet_services.rb +4 -0
- data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +75 -0
- metadata +9 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f3e8b0865b88790b85de1ad455a9b262603722e1919b25af614994765794d704
|
|
4
|
+
data.tar.gz: 8f16bbf7b16594ef9a4ff31d91e7fac5b67d36edd26021f297be09a110da95cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e97396572fb70e02900174cc177dc435159083d844f4f44a6dd9c854543af13eb866cbfd17265ac6c4239f260bc78e171eb02cfd16c564bf1e2d3203241d8661
|
|
7
|
+
data.tar.gz: e1db85c6c73756534c68018ee32803beda36d50237511e259ba693c269a0c671e0432e4417083b99bad0feb50b984244c16f33eab36d755930c833496fff27fc
|
data/lib/ruflet/version.rb
CHANGED
data/lib/ruflet_ui/ruflet/dsl.rb
CHANGED
|
@@ -51,6 +51,16 @@ module Ruflet
|
|
|
51
51
|
def control(type, **props, &block) = _pending_app.control(type, **props, &block)
|
|
52
52
|
def widget(type, **props, &block) = _pending_app.widget(type, **props, &block)
|
|
53
53
|
def service(type, **props, &block) = _pending_app.service(type, **props, &block)
|
|
54
|
+
def view(children = nil, **props, &block) = _pending_app.view(children, **props, &block)
|
|
55
|
+
def base_page(**props, &block) = _pending_app.base_page(**props, &block)
|
|
56
|
+
def basepage(**props, &block) = _pending_app.basepage(**props, &block)
|
|
57
|
+
def dialogs(controls = nil, **props) = _pending_app.dialogs(controls, **props)
|
|
58
|
+
def pagelet(content = nil, **props, &block) = _pending_app.pagelet(content, **props, &block)
|
|
59
|
+
def ruflet_app(**props) = _pending_app.ruflet_app(**props)
|
|
60
|
+
def rufletapp(**props) = _pending_app.rufletapp(**props)
|
|
61
|
+
def service_registry(services = nil, **props) = _pending_app.service_registry(services, **props)
|
|
62
|
+
def serviceregistry(services = nil, **props) = _pending_app.serviceregistry(services, **props)
|
|
63
|
+
def window(**props) = _pending_app.window(**props)
|
|
54
64
|
def column(children = nil, **props, &block) = _pending_app.column(children, **props, &block)
|
|
55
65
|
def center(**props, &block) = _pending_app.center(**props, &block)
|
|
56
66
|
def row(children = nil, **props, &block) = _pending_app.row(children, **props, &block)
|
|
@@ -62,7 +72,31 @@ module Ruflet
|
|
|
62
72
|
def animatedswitcher(content = nil, **props) = _pending_app.animatedswitcher(content, **props)
|
|
63
73
|
def animation(duration = nil, **props) = _pending_app.animation(duration, **props)
|
|
64
74
|
def animation_style(**props) = _pending_app.animation_style(**props)
|
|
75
|
+
def accelerometer(**props) = _pending_app.accelerometer(**props)
|
|
65
76
|
def audio(**props) = _pending_app.audio(**props)
|
|
77
|
+
def audio_recorder(**props) = _pending_app.audio_recorder(**props)
|
|
78
|
+
def barometer(**props) = _pending_app.barometer(**props)
|
|
79
|
+
def battery(**props) = _pending_app.battery(**props)
|
|
80
|
+
def browser_context_menu(**props) = _pending_app.browser_context_menu(**props)
|
|
81
|
+
def camera(**props) = _pending_app.camera(**props)
|
|
82
|
+
def connectivity(**props) = _pending_app.connectivity(**props)
|
|
83
|
+
def file_picker(**props) = _pending_app.file_picker(**props)
|
|
84
|
+
def flashlight(**props) = _pending_app.flashlight(**props)
|
|
85
|
+
def geolocator(**props) = _pending_app.geolocator(**props)
|
|
86
|
+
def gyroscope(**props) = _pending_app.gyroscope(**props)
|
|
87
|
+
def haptic_feedback(**props) = _pending_app.haptic_feedback(**props)
|
|
88
|
+
def magnetometer(**props) = _pending_app.magnetometer(**props)
|
|
89
|
+
def permission_handler(**props) = _pending_app.permission_handler(**props)
|
|
90
|
+
def screen_brightness(**props) = _pending_app.screen_brightness(**props)
|
|
91
|
+
def secure_storage(**props) = _pending_app.secure_storage(**props)
|
|
92
|
+
def semantics_service(**props) = _pending_app.semantics_service(**props)
|
|
93
|
+
def shake_detector(**props) = _pending_app.shake_detector(**props)
|
|
94
|
+
def share(**props) = _pending_app.share(**props)
|
|
95
|
+
def shared_preferences(**props) = _pending_app.shared_preferences(**props)
|
|
96
|
+
def storage_paths(**props) = _pending_app.storage_paths(**props)
|
|
97
|
+
def url_launcher(**props) = _pending_app.url_launcher(**props)
|
|
98
|
+
def user_accelerometer(**props) = _pending_app.user_accelerometer(**props)
|
|
99
|
+
def wakelock(**props) = _pending_app.wakelock(**props)
|
|
66
100
|
def auto_complete(suggestions = nil, **props) = _pending_app.auto_complete(suggestions, **props)
|
|
67
101
|
def autocomplete(suggestions = nil, **props) = _pending_app.autocomplete(suggestions, **props)
|
|
68
102
|
def auto_complete_suggestion(key = nil, **props) = _pending_app.auto_complete_suggestion(key, **props)
|
|
@@ -70,6 +104,8 @@ module Ruflet
|
|
|
70
104
|
def autocompletesuggestion(key = nil, **props) = _pending_app.autocompletesuggestion(key, **props)
|
|
71
105
|
def context_menu(content = nil, **props) = _pending_app.context_menu(content, **props)
|
|
72
106
|
def contextmenu(content = nil, **props) = _pending_app.contextmenu(content, **props)
|
|
107
|
+
def context_menu_action(content = nil, **props) = _pending_app.context_menu_action(content, **props)
|
|
108
|
+
def contextmenuaction(content = nil, **props) = _pending_app.contextmenuaction(content, **props)
|
|
73
109
|
def autofill_group(content = nil, **props) = _pending_app.autofill_group(content, **props)
|
|
74
110
|
def autofillgroup(content = nil, **props) = _pending_app.autofillgroup(content, **props)
|
|
75
111
|
def hero(content = nil, **props) = _pending_app.hero(content, **props)
|
|
@@ -133,6 +169,14 @@ module Ruflet
|
|
|
133
169
|
def polygonmarker(**props) = _pending_app.polygonmarker(**props)
|
|
134
170
|
def simple_attribution(**props) = _pending_app.simple_attribution(**props)
|
|
135
171
|
def simpleattribution(**props) = _pending_app.simpleattribution(**props)
|
|
172
|
+
def map_layer(**props) = _pending_app.map_layer(**props)
|
|
173
|
+
def maplayer(**props) = _pending_app.maplayer(**props)
|
|
174
|
+
def rich_attribution(attributions = nil, **props) = _pending_app.rich_attribution(attributions, **props)
|
|
175
|
+
def richattribution(attributions = nil, **props) = _pending_app.richattribution(attributions, **props)
|
|
176
|
+
def image_source_attribution(image = nil, **props) = _pending_app.image_source_attribution(image, **props)
|
|
177
|
+
def imagesourceattribution(image = nil, **props) = _pending_app.imagesourceattribution(image, **props)
|
|
178
|
+
def text_source_attribution(text = nil, **props) = _pending_app.text_source_attribution(text, **props)
|
|
179
|
+
def textsourceattribution(text = nil, **props) = _pending_app.textsourceattribution(text, **props)
|
|
136
180
|
def list_view(children = nil, **props) = _pending_app.list_view(children, **props)
|
|
137
181
|
def listview(children = nil, **props) = _pending_app.listview(children, **props)
|
|
138
182
|
def menu_bar(children = nil, **props) = _pending_app.menu_bar(children, **props)
|
|
@@ -160,6 +204,13 @@ module Ruflet
|
|
|
160
204
|
def datarow(cells = nil, **props) = _pending_app.datarow(cells, **props)
|
|
161
205
|
def data_cell(content = nil, **props) = _pending_app.data_cell(content, **props)
|
|
162
206
|
def datacell(content = nil, **props) = _pending_app.datacell(content, **props)
|
|
207
|
+
def option(key = nil, **props) = _pending_app.option(key, **props)
|
|
208
|
+
def data_table2(columns = nil, **props) = _pending_app.data_table2(columns, **props)
|
|
209
|
+
def datatable2(columns = nil, **props) = _pending_app.datatable2(columns, **props)
|
|
210
|
+
def data_column2(label = nil, **props) = _pending_app.data_column2(label, **props)
|
|
211
|
+
def datacolumn2(label = nil, **props) = _pending_app.datacolumn2(label, **props)
|
|
212
|
+
def data_row2(cells = nil, **props) = _pending_app.data_row2(cells, **props)
|
|
213
|
+
def datarow2(cells = nil, **props) = _pending_app.datarow2(cells, **props)
|
|
163
214
|
def expansion_tile(children = nil, **props) = _pending_app.expansion_tile(children, **props)
|
|
164
215
|
def expansiontile(children = nil, **props) = _pending_app.expansiontile(children, **props)
|
|
165
216
|
def expansion_panel(**props) = _pending_app.expansion_panel(**props)
|
|
@@ -178,6 +229,9 @@ module Ruflet
|
|
|
178
229
|
def pageview(children = nil, **props) = _pending_app.pageview(children, **props)
|
|
179
230
|
def progress_ring(**props) = _pending_app.progress_ring(**props)
|
|
180
231
|
def progressring(**props) = _pending_app.progressring(**props)
|
|
232
|
+
def picker(children = nil, **props) = _pending_app.picker(children, **props)
|
|
233
|
+
def timer_picker(**props) = _pending_app.timer_picker(**props)
|
|
234
|
+
def timerpicker(**props) = _pending_app.timerpicker(**props)
|
|
181
235
|
def spinkit(**props) = _pending_app.spinkit(**props)
|
|
182
236
|
def range_slider(**props) = _pending_app.range_slider(**props)
|
|
183
237
|
def rangeslider(**props) = _pending_app.rangeslider(**props)
|
|
@@ -257,6 +311,10 @@ module Ruflet
|
|
|
257
311
|
def snackbaraction(label = nil, **props) = _pending_app.snackbaraction(label, **props)
|
|
258
312
|
def bottom_sheet(content = nil, **props) = _pending_app.bottom_sheet(content, **props)
|
|
259
313
|
def bottomsheet(content = nil, **props) = _pending_app.bottomsheet(content, **props)
|
|
314
|
+
def action_sheet(**props) = _pending_app.action_sheet(**props)
|
|
315
|
+
def actionsheet(**props) = _pending_app.actionsheet(**props)
|
|
316
|
+
def action_sheet_action(content = nil, **props) = _pending_app.action_sheet_action(content, **props)
|
|
317
|
+
def actionsheetaction(content = nil, **props) = _pending_app.actionsheetaction(content, **props)
|
|
260
318
|
def markdown(value = nil, **props) = _pending_app.markdown(value, **props)
|
|
261
319
|
def floating_action_button(**props) = _pending_app.floating_action_button(**props)
|
|
262
320
|
def floatingactionbutton(**props) = _pending_app.floatingactionbutton(**props)
|
|
@@ -319,6 +377,24 @@ module Ruflet
|
|
|
319
377
|
def web_view(**props) = _pending_app.web_view(**props)
|
|
320
378
|
def webview(**props) = _pending_app.webview(**props)
|
|
321
379
|
def video(**props) = _pending_app.video(**props)
|
|
380
|
+
def block_picker(**props) = _pending_app.block_picker(**props)
|
|
381
|
+
def blockpicker(**props) = _pending_app.blockpicker(**props)
|
|
382
|
+
def color_picker(**props) = _pending_app.color_picker(**props)
|
|
383
|
+
def colorpicker(**props) = _pending_app.colorpicker(**props)
|
|
384
|
+
def hue_ring_picker(**props) = _pending_app.hue_ring_picker(**props)
|
|
385
|
+
def hueringpicker(**props) = _pending_app.hueringpicker(**props)
|
|
386
|
+
def material_picker(**props) = _pending_app.material_picker(**props)
|
|
387
|
+
def materialpicker(**props) = _pending_app.materialpicker(**props)
|
|
388
|
+
def multiple_choice_block_picker(**props) = _pending_app.multiple_choice_block_picker(**props)
|
|
389
|
+
def multiplechoiceblockpicker(**props) = _pending_app.multiplechoiceblockpicker(**props)
|
|
390
|
+
def slide_picker(**props) = _pending_app.slide_picker(**props)
|
|
391
|
+
def slidepicker(**props) = _pending_app.slidepicker(**props)
|
|
392
|
+
def banner_ad(**props) = _pending_app.banner_ad(**props)
|
|
393
|
+
def bannerad(**props) = _pending_app.bannerad(**props)
|
|
394
|
+
def interstitial_ad(**props) = _pending_app.interstitial_ad(**props)
|
|
395
|
+
def interstitialad(**props) = _pending_app.interstitialad(**props)
|
|
396
|
+
def native_ad(**props) = _pending_app.native_ad(**props)
|
|
397
|
+
def nativead(**props) = _pending_app.nativead(**props)
|
|
322
398
|
def code_editor(value = nil, **props) = _pending_app.code_editor(value, **props)
|
|
323
399
|
def codeeditor(value = nil, **props) = _pending_app.codeeditor(value, **props)
|
|
324
400
|
def lottie(src = nil, **props) = _pending_app.lottie(src, **props)
|
|
@@ -30,9 +30,10 @@ module Ruflet
|
|
|
30
30
|
|
|
31
31
|
def parse_data(raw)
|
|
32
32
|
return raw unless raw.is_a?(String)
|
|
33
|
+
return raw unless Object.const_defined?(:JSON)
|
|
33
34
|
|
|
34
|
-
JSON.parse(raw)
|
|
35
|
-
rescue
|
|
35
|
+
Object.const_get(:JSON).parse(raw)
|
|
36
|
+
rescue StandardError
|
|
36
37
|
raw
|
|
37
38
|
end
|
|
38
39
|
|
|
@@ -48,7 +48,8 @@ module Ruflet
|
|
|
48
48
|
raw = data.is_a?(Hash) ? stringify_keys(data) : data
|
|
49
49
|
value =
|
|
50
50
|
if raw.is_a?(Hash)
|
|
51
|
-
|
|
51
|
+
key = %w[value v data state route].find { |candidate| raw.key?(candidate) }
|
|
52
|
+
key.nil? ? nil : raw[key]
|
|
52
53
|
else
|
|
53
54
|
raw
|
|
54
55
|
end
|
|
@@ -178,6 +178,8 @@ module Ruflet
|
|
|
178
178
|
@page_event_handlers = {}
|
|
179
179
|
@view_props = {}
|
|
180
180
|
@page_props = { "route" => (client_details["route"] || "/") }
|
|
181
|
+
@published_control_states = {}
|
|
182
|
+
@published_shell_state = nil
|
|
181
183
|
@window = build_client_window(client_details["window"])
|
|
182
184
|
@page_props["window"] = @window
|
|
183
185
|
@overlay_container = Ruflet::Control.new(
|
|
@@ -229,6 +231,18 @@ module Ruflet
|
|
|
229
231
|
@page_props["route"] = value
|
|
230
232
|
end
|
|
231
233
|
|
|
234
|
+
# A resumed Page keeps its Ruby controls and event handlers, but a newly
|
|
235
|
+
# connected client has not mounted any of that state yet. Invalidate only
|
|
236
|
+
# the client-side publication snapshot so the next update sends the full
|
|
237
|
+
# page shell, including the internal overlay, dialog, and service roots.
|
|
238
|
+
def prepare_for_reconnect!
|
|
239
|
+
@overlay_container_mounted = false
|
|
240
|
+
@dialogs_container_mounted = false
|
|
241
|
+
@services_container_mounted = false
|
|
242
|
+
@published_shell_state = nil
|
|
243
|
+
self
|
|
244
|
+
end
|
|
245
|
+
|
|
232
246
|
def vertical_alignment
|
|
233
247
|
@page_props["vertical_alignment"] || @view_props["vertical_alignment"]
|
|
234
248
|
end
|
|
@@ -313,6 +327,7 @@ module Ruflet
|
|
|
313
327
|
@overlay_container_mounted = true if @overlay_container.wire_id
|
|
314
328
|
@dialogs_container_mounted = true if @dialogs_container.wire_id
|
|
315
329
|
@services_container_mounted = true if @services_container.wire_id
|
|
330
|
+
capture_published_wire_state!
|
|
316
331
|
patch
|
|
317
332
|
end
|
|
318
333
|
|
|
@@ -1281,7 +1296,7 @@ module Ruflet
|
|
|
1281
1296
|
|
|
1282
1297
|
def update(control_or_id = nil, **props)
|
|
1283
1298
|
if control_or_id.nil? && props.empty?
|
|
1284
|
-
|
|
1299
|
+
send_changed_control_patches
|
|
1285
1300
|
return self
|
|
1286
1301
|
end
|
|
1287
1302
|
|
|
@@ -1310,8 +1325,10 @@ module Ruflet
|
|
|
1310
1325
|
|
|
1311
1326
|
# Keep runtime control tree aligned with incremental patches.
|
|
1312
1327
|
if patch.key?("controls")
|
|
1328
|
+
replacement_controls = Array(patch["controls"]).dup
|
|
1313
1329
|
control.children.clear
|
|
1314
|
-
|
|
1330
|
+
replacement_controls.each { |child| control.children << child if child.is_a?(Control) }
|
|
1331
|
+
patch["controls"] = replacement_controls
|
|
1315
1332
|
end
|
|
1316
1333
|
|
|
1317
1334
|
visited = Set.new
|
|
@@ -1323,6 +1340,7 @@ module Ruflet
|
|
|
1323
1340
|
"id" => wire_id,
|
|
1324
1341
|
"patch" => [[0], *patch_ops]
|
|
1325
1342
|
})
|
|
1343
|
+
capture_published_control_tree!(control)
|
|
1326
1344
|
|
|
1327
1345
|
self
|
|
1328
1346
|
end
|
|
@@ -1336,11 +1354,24 @@ module Ruflet
|
|
|
1336
1354
|
end
|
|
1337
1355
|
|
|
1338
1356
|
def apply_client_update(control_or_id, props)
|
|
1357
|
+
if page_control_target?(control_or_id)
|
|
1358
|
+
patch = normalize_props(props || {})
|
|
1359
|
+
@client_details.merge!(patch)
|
|
1360
|
+
# These are live client measurements. Keep the page getters current as
|
|
1361
|
+
# well, without consuming route changes before their event is dispatched.
|
|
1362
|
+
%w[width height platform_brightness media].each do |key|
|
|
1363
|
+
@page_props[key] = patch[key] if patch.key?(key)
|
|
1364
|
+
end
|
|
1365
|
+
capture_published_shell_state!
|
|
1366
|
+
return self
|
|
1367
|
+
end
|
|
1368
|
+
|
|
1339
1369
|
control = resolve_control(control_or_id)
|
|
1340
1370
|
return self unless control
|
|
1341
1371
|
|
|
1342
1372
|
patch = normalize_props(props || {})
|
|
1343
1373
|
patch.each { |k, v| control.props[k] = v }
|
|
1374
|
+
capture_published_control_tree!(control)
|
|
1344
1375
|
|
|
1345
1376
|
remove_dialog_tracking(control) if patch.key?("open") && patch["open"] == false
|
|
1346
1377
|
|
|
@@ -1353,6 +1384,7 @@ module Ruflet
|
|
|
1353
1384
|
route_from_event = extract_route(data)
|
|
1354
1385
|
return if route_from_event && route_from_event == @page_props["route"]
|
|
1355
1386
|
@page_props["route"] = route_from_event if route_from_event
|
|
1387
|
+
capture_published_shell_state!
|
|
1356
1388
|
end
|
|
1357
1389
|
dispatch_page_event(name: name, data: data)
|
|
1358
1390
|
return
|
|
@@ -1362,7 +1394,13 @@ module Ruflet
|
|
|
1362
1394
|
return unless control
|
|
1363
1395
|
|
|
1364
1396
|
event = Event.new(name: name, target: target, raw_data: data, page: self, control: control)
|
|
1365
|
-
|
|
1397
|
+
if %w[change select select_change].include?(name.to_s)
|
|
1398
|
+
apply_event_value_to_control(control, event)
|
|
1399
|
+
# The client already owns this value. Treat it as published before the
|
|
1400
|
+
# handler runs so a later bare page.update only sends application-side
|
|
1401
|
+
# mutations, not the value that originated on the client.
|
|
1402
|
+
capture_published_control_tree!(control)
|
|
1403
|
+
end
|
|
1366
1404
|
control.emit(name, event)
|
|
1367
1405
|
|
|
1368
1406
|
if name.to_s == "dismiss" && remove_dialog_tracking(control)
|
|
@@ -1533,6 +1571,202 @@ module Ruflet
|
|
|
1533
1571
|
@sender.call(action, payload)
|
|
1534
1572
|
end
|
|
1535
1573
|
|
|
1574
|
+
# Bare page.update is the public commit point for direct mutations such as
|
|
1575
|
+
# `list.children.replace(...)`. Keep a shallow, immutable wire snapshot of
|
|
1576
|
+
# every mounted control so the commit can target only controls whose own
|
|
1577
|
+
# properties or child references changed. Descendant contents are tracked
|
|
1578
|
+
# independently: changing a Text value patches the Text, while replacing a
|
|
1579
|
+
# Column's children patches the Column.
|
|
1580
|
+
def send_changed_control_patches
|
|
1581
|
+
refresh_control_indexes!
|
|
1582
|
+
current = build_wire_state_snapshot
|
|
1583
|
+
|
|
1584
|
+
# Navigation, root controls, and page/view chrome are page-owned rather
|
|
1585
|
+
# than regular mounted controls. Retain the complete view patch as the
|
|
1586
|
+
# safe fallback whenever that shell changes.
|
|
1587
|
+
if @published_shell_state.nil? || current[:shell] != @published_shell_state
|
|
1588
|
+
send_view_patch
|
|
1589
|
+
return
|
|
1590
|
+
end
|
|
1591
|
+
|
|
1592
|
+
dirty_ids = current[:controls].each_with_object(Set.new) do |(wire_id, entry), dirty|
|
|
1593
|
+
prior = @published_control_states[wire_id]
|
|
1594
|
+
dirty << wire_id if prior && prior != entry[:state]
|
|
1595
|
+
end
|
|
1596
|
+
|
|
1597
|
+
# A changed parent patch serializes its newly referenced children, so a
|
|
1598
|
+
# second patch for a dirty descendant would be redundant and can race the
|
|
1599
|
+
# parent's replacement on the client.
|
|
1600
|
+
targets = dirty_ids.reject do |wire_id|
|
|
1601
|
+
ancestor = current[:parents][wire_id]
|
|
1602
|
+
found = false
|
|
1603
|
+
while ancestor
|
|
1604
|
+
if dirty_ids.include?(ancestor)
|
|
1605
|
+
found = true
|
|
1606
|
+
break
|
|
1607
|
+
end
|
|
1608
|
+
ancestor = current[:parents][ancestor]
|
|
1609
|
+
end
|
|
1610
|
+
found
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
targets.each do |wire_id|
|
|
1614
|
+
entry = current[:controls][wire_id]
|
|
1615
|
+
patch_ops = changed_control_patch_ops(
|
|
1616
|
+
entry[:control],
|
|
1617
|
+
@published_control_states.fetch(wire_id),
|
|
1618
|
+
entry[:state]
|
|
1619
|
+
)
|
|
1620
|
+
next if patch_ops.empty?
|
|
1621
|
+
|
|
1622
|
+
send_message(Protocol::ACTIONS[:patch_control], {
|
|
1623
|
+
"id" => wire_id,
|
|
1624
|
+
"patch" => [[0], *patch_ops]
|
|
1625
|
+
})
|
|
1626
|
+
end
|
|
1627
|
+
|
|
1628
|
+
publish_wire_state_snapshot!(current)
|
|
1629
|
+
end
|
|
1630
|
+
|
|
1631
|
+
def changed_control_patch_ops(control, prior, current)
|
|
1632
|
+
operations = []
|
|
1633
|
+
prior_props = prior.fetch("props")
|
|
1634
|
+
current_props = current.fetch("props")
|
|
1635
|
+
|
|
1636
|
+
(prior_props.keys | current_props.keys).each do |key|
|
|
1637
|
+
next if prior_props[key] == current_props[key]
|
|
1638
|
+
|
|
1639
|
+
value = control.props.key?(key) ? control.props[key] : nil
|
|
1640
|
+
operations << [0, 0, key, serialize_patch_value(value)]
|
|
1641
|
+
end
|
|
1642
|
+
|
|
1643
|
+
if prior.fetch("children") != current.fetch("children")
|
|
1644
|
+
operations << [0, 0, "controls", serialize_patch_value(control.children)]
|
|
1645
|
+
end
|
|
1646
|
+
operations
|
|
1647
|
+
end
|
|
1648
|
+
|
|
1649
|
+
def build_wire_state_snapshot
|
|
1650
|
+
controls = {}
|
|
1651
|
+
parents = {}
|
|
1652
|
+
visited = Set.new
|
|
1653
|
+
|
|
1654
|
+
roots = @views.any? ? @views : @root_controls
|
|
1655
|
+
roots.each { |control| collect_control_wire_state(control, nil, controls, parents, visited) }
|
|
1656
|
+
unless @views.any?
|
|
1657
|
+
@view_props.each_value do |value|
|
|
1658
|
+
collect_embedded_wire_state(value, nil, controls, parents, visited)
|
|
1659
|
+
end
|
|
1660
|
+
end
|
|
1661
|
+
@page_props.each_value do |value|
|
|
1662
|
+
collect_embedded_wire_state(value, nil, controls, parents, visited)
|
|
1663
|
+
end
|
|
1664
|
+
|
|
1665
|
+
{
|
|
1666
|
+
controls: controls,
|
|
1667
|
+
parents: parents,
|
|
1668
|
+
shell: current_shell_wire_state
|
|
1669
|
+
}
|
|
1670
|
+
end
|
|
1671
|
+
|
|
1672
|
+
def collect_control_wire_state(control, parent_id, controls, parents, visited)
|
|
1673
|
+
return unless control
|
|
1674
|
+
return if visited.include?(control.object_id)
|
|
1675
|
+
|
|
1676
|
+
visited << control.object_id
|
|
1677
|
+
wire_id = control.wire_id
|
|
1678
|
+
return unless wire_id
|
|
1679
|
+
|
|
1680
|
+
parents[wire_id] = parent_id if parent_id
|
|
1681
|
+
controls[wire_id] = {
|
|
1682
|
+
control: control,
|
|
1683
|
+
state: control_local_wire_state(control)
|
|
1684
|
+
}
|
|
1685
|
+
control.children.each do |child|
|
|
1686
|
+
collect_control_wire_state(child, wire_id, controls, parents, visited)
|
|
1687
|
+
end
|
|
1688
|
+
control.props.each_value do |value|
|
|
1689
|
+
collect_embedded_wire_state(value, wire_id, controls, parents, visited)
|
|
1690
|
+
end
|
|
1691
|
+
end
|
|
1692
|
+
|
|
1693
|
+
def collect_embedded_wire_state(value, parent_id, controls, parents, visited)
|
|
1694
|
+
case value
|
|
1695
|
+
when Control
|
|
1696
|
+
collect_control_wire_state(value, parent_id, controls, parents, visited)
|
|
1697
|
+
when Array
|
|
1698
|
+
value.each do |entry|
|
|
1699
|
+
collect_embedded_wire_state(entry, parent_id, controls, parents, visited)
|
|
1700
|
+
end
|
|
1701
|
+
when Hash
|
|
1702
|
+
value.each_value do |entry|
|
|
1703
|
+
collect_embedded_wire_state(entry, parent_id, controls, parents, visited)
|
|
1704
|
+
end
|
|
1705
|
+
end
|
|
1706
|
+
end
|
|
1707
|
+
|
|
1708
|
+
def control_local_wire_state(control)
|
|
1709
|
+
{
|
|
1710
|
+
"type" => control.type,
|
|
1711
|
+
"props" => comparison_wire_value(control.props),
|
|
1712
|
+
"children" => control.children.map(&:wire_id)
|
|
1713
|
+
}
|
|
1714
|
+
end
|
|
1715
|
+
|
|
1716
|
+
def current_shell_wire_state
|
|
1717
|
+
{
|
|
1718
|
+
"mode" => (@views.any? ? "views" : "implicit_view"),
|
|
1719
|
+
"roots" => (@views.any? ? @views : @root_controls).map(&:wire_id),
|
|
1720
|
+
"view_props" => comparison_wire_value(@view_props),
|
|
1721
|
+
"page_props" => comparison_wire_value(@page_props)
|
|
1722
|
+
}
|
|
1723
|
+
end
|
|
1724
|
+
|
|
1725
|
+
# Controls are references in their parent's local state. Their contents
|
|
1726
|
+
# are deliberately excluded and tracked under their own wire IDs.
|
|
1727
|
+
def comparison_wire_value(value)
|
|
1728
|
+
case value
|
|
1729
|
+
when Control
|
|
1730
|
+
[Control, value.wire_id]
|
|
1731
|
+
when Array
|
|
1732
|
+
value.map { |entry| comparison_wire_value(entry) }
|
|
1733
|
+
when Hash
|
|
1734
|
+
value.each_with_object({}) do |(key, entry), result|
|
|
1735
|
+
result[key] = comparison_wire_value(entry)
|
|
1736
|
+
end
|
|
1737
|
+
when String
|
|
1738
|
+
value.dup
|
|
1739
|
+
else
|
|
1740
|
+
begin
|
|
1741
|
+
value.dup
|
|
1742
|
+
rescue TypeError
|
|
1743
|
+
value
|
|
1744
|
+
end
|
|
1745
|
+
end
|
|
1746
|
+
end
|
|
1747
|
+
|
|
1748
|
+
def capture_published_wire_state!
|
|
1749
|
+
publish_wire_state_snapshot!(build_wire_state_snapshot)
|
|
1750
|
+
end
|
|
1751
|
+
|
|
1752
|
+
def publish_wire_state_snapshot!(snapshot)
|
|
1753
|
+
@published_control_states = snapshot[:controls].transform_values { |entry| entry[:state] }
|
|
1754
|
+
@published_shell_state = snapshot[:shell]
|
|
1755
|
+
end
|
|
1756
|
+
|
|
1757
|
+
def capture_published_control_tree!(control)
|
|
1758
|
+
controls = {}
|
|
1759
|
+
parents = {}
|
|
1760
|
+
collect_control_wire_state(control, nil, controls, parents, Set.new)
|
|
1761
|
+
controls.each do |wire_id, entry|
|
|
1762
|
+
@published_control_states[wire_id] = entry[:state]
|
|
1763
|
+
end
|
|
1764
|
+
end
|
|
1765
|
+
|
|
1766
|
+
def capture_published_shell_state!
|
|
1767
|
+
@published_shell_state = current_shell_wire_state if @published_shell_state
|
|
1768
|
+
end
|
|
1769
|
+
|
|
1536
1770
|
def replace_root_controls(controls)
|
|
1537
1771
|
visited = Set.new
|
|
1538
1772
|
controls.each { |control| register_control_tree(control, visited) }
|
|
@@ -1559,6 +1793,7 @@ module Ruflet
|
|
|
1559
1793
|
@overlay_container_mounted = true if @overlay_container.wire_id
|
|
1560
1794
|
@dialogs_container_mounted = true if @dialogs_container.wire_id
|
|
1561
1795
|
@services_container_mounted = true if @services_container.wire_id
|
|
1796
|
+
capture_published_wire_state!
|
|
1562
1797
|
end
|
|
1563
1798
|
|
|
1564
1799
|
def register_control_tree(control, visited = Set.new)
|
|
@@ -1778,6 +2013,7 @@ module Ruflet
|
|
|
1778
2013
|
"id" => @overlay_container.wire_id,
|
|
1779
2014
|
"patch" => [[0], [0, 0, "controls", serialize_patch_value(@overlay_container.children)]]
|
|
1780
2015
|
})
|
|
2016
|
+
capture_published_control_tree!(@overlay_container)
|
|
1781
2017
|
else
|
|
1782
2018
|
send_view_patch
|
|
1783
2019
|
end
|
|
@@ -1795,6 +2031,7 @@ module Ruflet
|
|
|
1795
2031
|
"id" => @services_container.wire_id,
|
|
1796
2032
|
"patch" => [[0], [0, 0, "_services", serialize_patch_value(@services_container.props["_services"])]]
|
|
1797
2033
|
})
|
|
2034
|
+
capture_published_control_tree!(@services_container)
|
|
1798
2035
|
else
|
|
1799
2036
|
send_view_patch
|
|
1800
2037
|
end
|
|
@@ -1808,6 +2045,7 @@ module Ruflet
|
|
|
1808
2045
|
"id" => @dialogs_container.wire_id,
|
|
1809
2046
|
"patch" => [[0], [0, 0, "controls", serialize_patch_value(@dialogs_container.props["controls"])]]
|
|
1810
2047
|
})
|
|
2048
|
+
capture_published_control_tree!(@dialogs_container)
|
|
1811
2049
|
else
|
|
1812
2050
|
send_view_patch
|
|
1813
2051
|
end
|
|
@@ -1841,7 +2079,7 @@ module Ruflet
|
|
|
1841
2079
|
end
|
|
1842
2080
|
|
|
1843
2081
|
def assign_split_prop(key, value)
|
|
1844
|
-
if key == "vertical_alignment" || key == "horizontal_alignment"
|
|
2082
|
+
if key == "vertical_alignment" || key == "horizontal_alignment" || key == "scroll"
|
|
1845
2083
|
@page_props[key] = value
|
|
1846
2084
|
@view_props[key] = value
|
|
1847
2085
|
elsif DIALOG_PROP_KEYS.include?(key)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "controls/ruflet_controls"
|
|
4
4
|
require_relative "services/ruflet_services"
|
|
5
|
+
require_relative "platform_control_contracts"
|
|
5
6
|
require_relative "../control"
|
|
6
7
|
|
|
7
8
|
module Ruflet
|
|
@@ -12,6 +13,7 @@ module Ruflet
|
|
|
12
13
|
CLASS_MAP =
|
|
13
14
|
Services::RufletServices::CLASS_MAP
|
|
14
15
|
.merge(Controls::RufletControls::CLASS_MAP)
|
|
16
|
+
.merge(PlatformControlContracts::CLASS_MAP)
|
|
15
17
|
.freeze
|
|
16
18
|
EXTENSION_CLASS_MAP = {}
|
|
17
19
|
CONSTRUCTOR_KEYWORDS_CACHE = {}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "material_control_methods"
|
|
4
|
+
require_relative "platform_control_methods"
|
|
4
5
|
require_relative "cupertino_control_methods"
|
|
5
6
|
|
|
6
7
|
module Ruflet
|
|
7
8
|
module UI
|
|
8
9
|
module ControlMethods
|
|
9
10
|
include MaterialControlMethods
|
|
11
|
+
include PlatformControlMethods
|
|
12
|
+
# Compatibility aliases only. They emit the same canonical wire types as
|
|
13
|
+
# the methods above and never select the visual renderer.
|
|
10
14
|
include CupertinoControlMethods
|
|
11
15
|
|
|
12
16
|
def control(type, **props, &block) = build_widget(type, **props, &block)
|
|
@@ -7,7 +7,26 @@ module Ruflet
|
|
|
7
7
|
require_relative "cupertino_control_registry"
|
|
8
8
|
require_relative "controls/ruflet_controls"
|
|
9
9
|
require_relative "services/ruflet_services"
|
|
10
|
-
|
|
10
|
+
require_relative "platform_control_contracts"
|
|
11
|
+
# Controls whose Ruby name and wire name differ on purpose. The client
|
|
12
|
+
# Native Ruflet clients use RufletApp as the canonical wire type while
|
|
13
|
+
# the Ruby API remains ruflet_app.
|
|
14
|
+
#
|
|
15
|
+
# RufletAppControl::WIRE already says this, but that is only read when the
|
|
16
|
+
# control resolves to its own class. Serialization otherwise derives the
|
|
17
|
+
# wire name from the type and must still send the canonical RufletApp.
|
|
18
|
+
# Map it here so both paths agree. to_patch also looks the type up with
|
|
19
|
+
# underscores removed, so register that spelling too.
|
|
20
|
+
SHARED_TYPE_MAP = {
|
|
21
|
+
"ruflet_app" => "RufletApp",
|
|
22
|
+
"rufletapp" => "RufletApp"
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
TYPE_MAP = MaterialControlRegistry::TYPE_MAP
|
|
26
|
+
.merge(CupertinoControlRegistry::TYPE_MAP)
|
|
27
|
+
.merge(SHARED_TYPE_MAP)
|
|
28
|
+
.merge(PlatformControlContracts::TYPE_MAP)
|
|
29
|
+
.freeze
|
|
11
30
|
SCHEMA_EVENT_PROPS =
|
|
12
31
|
Controls::RufletControls::CLASS_MAP
|
|
13
32
|
.merge(Services::RufletServices::CLASS_MAP)
|
|
@@ -6,7 +6,7 @@ module Ruflet
|
|
|
6
6
|
module RufletComponents
|
|
7
7
|
class CupertinoActionSheetControl < Ruflet::Control
|
|
8
8
|
TYPE = "cupertinoactionsheet".freeze
|
|
9
|
-
WIRE = "
|
|
9
|
+
WIRE = "ActionSheet".freeze
|
|
10
10
|
|
|
11
11
|
KEYWORDS = [:actions, :align, :animate_align, :animate_margin, :animate_offset, :animate_opacity, :animate_position, :animate_rotation, :animate_scale, :animate_size, :aspect_ratio, :badge, :bottom, :cancel, :col, :data, :disabled, :expand, :expand_loose, :height, :key, :left, :margin, :message, :offset, :opacity, :right, :rotate, :rtl, :scale, :size_change_interval, :title, :tooltip, :top, :visible, :width, :on_animation_end, :on_size_change].freeze
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ module Ruflet
|
|
|
6
6
|
module RufletComponents
|
|
7
7
|
class CupertinoActionSheetActionControl < Ruflet::Control
|
|
8
8
|
TYPE = "cupertinoactionsheetaction".freeze
|
|
9
|
-
WIRE = "
|
|
9
|
+
WIRE = "ActionSheetAction".freeze
|
|
10
10
|
|
|
11
11
|
KEYWORDS = [:align, :animate_align, :animate_margin, :animate_offset, :animate_opacity, :animate_position, :animate_rotation, :animate_scale, :animate_size, :aspect_ratio, :badge, :bottom, :col, :content, :data, :default, :destructive, :disabled, :expand, :expand_loose, :height, :key, :left, :margin, :mouse_cursor, :offset, :opacity, :right, :rotate, :rtl, :scale, :size_change_interval, :tooltip, :top, :visible, :width, :on_animation_end, :on_click, :on_size_change].freeze
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ module Ruflet
|
|
|
6
6
|
module RufletComponents
|
|
7
7
|
class CupertinoActivityIndicatorControl < Ruflet::Control
|
|
8
8
|
TYPE = "cupertinoactivityindicator".freeze
|
|
9
|
-
WIRE = "
|
|
9
|
+
WIRE = "ProgressRing".freeze
|
|
10
10
|
|
|
11
11
|
KEYWORDS = [:align, :animate_align, :animate_margin, :animate_offset, :animate_opacity, :animate_position, :animate_rotation, :animate_scale, :animate_size, :animating, :aspect_ratio, :badge, :bottom, :col, :color, :data, :disabled, :expand, :expand_loose, :height, :key, :left, :margin, :offset, :opacity, :progress, :radius, :right, :rotate, :rtl, :scale, :size_change_interval, :tooltip, :top, :visible, :width, :on_animation_end, :on_size_change].freeze
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ module Ruflet
|
|
|
6
6
|
module RufletComponents
|
|
7
7
|
class CupertinoAlertDialogControl < Ruflet::Control
|
|
8
8
|
TYPE = "cupertinoalertdialog".freeze
|
|
9
|
-
WIRE = "
|
|
9
|
+
WIRE = "AlertDialog".freeze
|
|
10
10
|
|
|
11
11
|
def initialize(id: nil, actions: nil, adaptive: nil, badge: nil, barrier_color: nil, col: nil, content: nil, data: nil, disabled: nil, expand: nil, expand_loose: nil, inset_animation: nil, key: nil, modal: nil, opacity: nil, open: nil, rtl: nil, title: nil, tooltip: nil, visible: nil, on_dismiss: nil)
|
|
12
12
|
actions = [] if actions.nil?
|
|
@@ -6,7 +6,7 @@ module Ruflet
|
|
|
6
6
|
module RufletComponents
|
|
7
7
|
class CupertinoAppBarControl < Ruflet::Control
|
|
8
8
|
TYPE = "cupertinoappbar".freeze
|
|
9
|
-
WIRE = "
|
|
9
|
+
WIRE = "AppBar".freeze
|
|
10
10
|
|
|
11
11
|
def initialize(id: nil, automatic_background_visibility: nil, automatically_imply_leading: nil, automatically_imply_title: nil, badge: nil, bgcolor: nil, border: nil, brightness: nil, col: nil, data: nil, disabled: nil, enable_background_filter_blur: nil, expand: nil, expand_loose: nil, key: nil, large: nil, leading: nil, opacity: nil, padding: nil, previous_page_title: nil, rtl: nil, title: nil, tooltip: nil, trailing: nil, transition_between_routes: nil, visible: nil)
|
|
12
12
|
large = false if large.nil?
|
|
@@ -6,7 +6,7 @@ module Ruflet
|
|
|
6
6
|
module RufletComponents
|
|
7
7
|
class CupertinoBottomSheetControl < Ruflet::Control
|
|
8
8
|
TYPE = "cupertinobottomsheet".freeze
|
|
9
|
-
WIRE = "
|
|
9
|
+
WIRE = "BottomSheet".freeze
|
|
10
10
|
|
|
11
11
|
def initialize(id: nil, adaptive: nil, badge: nil, bgcolor: nil, col: nil, content: nil, data: nil, disabled: nil, expand: nil, expand_loose: nil, height: nil, key: nil, modal: nil, opacity: nil, open: nil, padding: nil, rtl: nil, tooltip: nil, visible: nil, on_dismiss: nil)
|
|
12
12
|
raise ArgumentError, "cupertino_bottom_sheet content is required" if content.nil?
|
|
@@ -6,7 +6,7 @@ module Ruflet
|
|
|
6
6
|
module RufletComponents
|
|
7
7
|
class CupertinoButtonControl < Ruflet::Control
|
|
8
8
|
TYPE = "cupertinobutton".freeze
|
|
9
|
-
WIRE = "
|
|
9
|
+
WIRE = "Button".freeze
|
|
10
10
|
|
|
11
11
|
KEYWORDS = [:align, :alignment, :animate_align, :animate_margin, :animate_offset, :animate_opacity, :animate_position, :animate_rotation, :animate_scale, :animate_size, :aspect_ratio, :autofocus, :badge, :bgcolor, :border_radius, :bottom, :col, :color, :content, :data, :disabled, :disabled_bgcolor, :expand, :expand_loose, :focus_color, :height, :icon, :icon_color, :key, :left, :margin, :min_size, :mouse_cursor, :offset, :opacity, :opacity_on_click, :padding, :right, :rotate, :rtl, :scale, :size, :size_change_interval, :tooltip, :top, :url, :visible, :width, :on_animation_end, :on_blur, :on_click, :on_focus, :on_long_press, :on_size_change].freeze
|
|
12
12
|
|