ruflet_core 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 (208) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3 -0
  3. data/lib/ruflet/version.rb +5 -0
  4. data/lib/ruflet.rb +3 -0
  5. data/lib/ruflet_core.rb +40 -0
  6. data/lib/ruflet_protocol/ruflet/protocol.rb +62 -0
  7. data/lib/ruflet_protocol.rb +4 -0
  8. data/lib/ruflet_ui/ruflet/app.rb +27 -0
  9. data/lib/ruflet_ui/ruflet/colors.rb +234 -0
  10. data/lib/ruflet_ui/ruflet/control.rb +281 -0
  11. data/lib/ruflet_ui/ruflet/dsl.rb +291 -0
  12. data/lib/ruflet_ui/ruflet/event.rb +42 -0
  13. data/lib/ruflet_ui/ruflet/events/gesture_events.rb +552 -0
  14. data/lib/ruflet_ui/ruflet/icon_data.rb +62 -0
  15. data/lib/ruflet_ui/ruflet/icons/cupertino/cupertino_icons.rb +54 -0
  16. data/lib/ruflet_ui/ruflet/icons/cupertino_icon_lookup.rb +70 -0
  17. data/lib/ruflet_ui/ruflet/icons/material/material_icons.rb +55 -0
  18. data/lib/ruflet_ui/ruflet/icons/material_icon_lookup.rb +70 -0
  19. data/lib/ruflet_ui/ruflet/page.rb +1222 -0
  20. data/lib/ruflet_ui/ruflet/types/geometry.rb +65 -0
  21. data/lib/ruflet_ui/ruflet/types/text_style.rb +191 -0
  22. data/lib/ruflet_ui/ruflet/ui/control_factory.rb +53 -0
  23. data/lib/ruflet_ui/ruflet/ui/control_methods.rb +17 -0
  24. data/lib/ruflet_ui/ruflet/ui/control_registry.rb +33 -0
  25. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheet_control.rb +57 -0
  26. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheetaction_control.rb +58 -0
  27. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactivityindicator_control.rb +57 -0
  28. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoalertdialog_control.rb +39 -0
  29. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoappbar_control.rb +44 -0
  30. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobottomsheet_control.rb +38 -0
  31. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobutton_control.rb +73 -0
  32. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocheckbox_control.rb +70 -0
  33. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenu_control.rb +34 -0
  34. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenuaction_control.rb +36 -0
  35. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodatepicker_control.rb +67 -0
  36. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodialogaction_control.rb +35 -0
  37. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinofilledbutton_control.rb +73 -0
  38. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinolisttile_control.rb +67 -0
  39. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinonavigationbar_control.rb +61 -0
  40. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinopicker_control.rb +66 -0
  41. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoradio_control.rb +66 -0
  42. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinosegmentedbutton_control.rb +63 -0
  43. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslider_control.rb +64 -0
  44. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslidingsegmentedbutton_control.rb +60 -0
  45. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoswitch_control.rb +73 -0
  46. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotextfield_control.rb +159 -0
  47. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotimerpicker_control.rb +61 -0
  48. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotintedbutton_control.rb +73 -0
  49. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/ruflet_controls.rb +89 -0
  50. data/lib/ruflet_ui/ruflet/ui/controls/materials/alertdialog_control.rb +58 -0
  51. data/lib/ruflet_ui/ruflet/ui/controls/materials/appbar_control.rb +53 -0
  52. data/lib/ruflet_ui/ruflet/ui/controls/materials/audio_control.rb +36 -0
  53. data/lib/ruflet_ui/ruflet/ui/controls/materials/autocomplete_control.rb +58 -0
  54. data/lib/ruflet_ui/ruflet/ui/controls/materials/badge_control.rb +31 -0
  55. data/lib/ruflet_ui/ruflet/ui/controls/materials/banner_control.rb +47 -0
  56. data/lib/ruflet_ui/ruflet/ui/controls/materials/bottomappbar_control.rb +62 -0
  57. data/lib/ruflet_ui/ruflet/ui/controls/materials/bottomsheet_control.rb +48 -0
  58. data/lib/ruflet_ui/ruflet/ui/controls/materials/button_control.rb +69 -0
  59. data/lib/ruflet_ui/ruflet/ui/controls/materials/card_control.rb +63 -0
  60. data/lib/ruflet_ui/ruflet/ui/controls/materials/chart_controls.rb +321 -0
  61. data/lib/ruflet_ui/ruflet/ui/controls/materials/checkbox_control.rb +76 -0
  62. data/lib/ruflet_ui/ruflet/ui/controls/materials/chip_control.rb +88 -0
  63. data/lib/ruflet_ui/ruflet/ui/controls/materials/circleavatar_control.rb +62 -0
  64. data/lib/ruflet_ui/ruflet/ui/controls/materials/container_control.rb +81 -0
  65. data/lib/ruflet_ui/ruflet/ui/controls/materials/contextmenu_control.rb +63 -0
  66. data/lib/ruflet_ui/ruflet/ui/controls/materials/datacell_control.rb +38 -0
  67. data/lib/ruflet_ui/ruflet/ui/controls/materials/datacolumn_control.rb +34 -0
  68. data/lib/ruflet_ui/ruflet/ui/controls/materials/datarow_control.rb +35 -0
  69. data/lib/ruflet_ui/ruflet/ui/controls/materials/datatable_control.rb +78 -0
  70. data/lib/ruflet_ui/ruflet/ui/controls/materials/datepicker_control.rb +55 -0
  71. data/lib/ruflet_ui/ruflet/ui/controls/materials/daterangepicker_control.rb +57 -0
  72. data/lib/ruflet_ui/ruflet/ui/controls/materials/divider_control.rb +36 -0
  73. data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdown_control.rb +99 -0
  74. data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdownm2_control.rb +119 -0
  75. data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdownoption_control.rb +35 -0
  76. data/lib/ruflet_ui/ruflet/ui/controls/materials/expansionpanel_control.rb +61 -0
  77. data/lib/ruflet_ui/ruflet/ui/controls/materials/expansionpanellist_control.rb +60 -0
  78. data/lib/ruflet_ui/ruflet/ui/controls/materials/expansiontile_control.rb +82 -0
  79. data/lib/ruflet_ui/ruflet/ui/controls/materials/filledbutton_control.rb +69 -0
  80. data/lib/ruflet_ui/ruflet/ui/controls/materials/fillediconbutton_control.rb +81 -0
  81. data/lib/ruflet_ui/ruflet/ui/controls/materials/filledtonalbutton_control.rb +69 -0
  82. data/lib/ruflet_ui/ruflet/ui/controls/materials/filledtonaliconbutton_control.rb +81 -0
  83. data/lib/ruflet_ui/ruflet/ui/controls/materials/floatingactionbutton_control.rb +73 -0
  84. data/lib/ruflet_ui/ruflet/ui/controls/materials/iconbutton_control.rb +81 -0
  85. data/lib/ruflet_ui/ruflet/ui/controls/materials/listtile_control.rb +87 -0
  86. data/lib/ruflet_ui/ruflet/ui/controls/materials/menubar_control.rb +33 -0
  87. data/lib/ruflet_ui/ruflet/ui/controls/materials/menuitembutton_control.rb +67 -0
  88. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationbar_control.rb +67 -0
  89. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationbardestination_control.rb +35 -0
  90. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationdrawer_control.rb +41 -0
  91. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationdrawerdestination_control.rb +34 -0
  92. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationrail_control.rb +70 -0
  93. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationraildestination_control.rb +36 -0
  94. data/lib/ruflet_ui/ruflet/ui/controls/materials/option_control.rb +35 -0
  95. data/lib/ruflet_ui/ruflet/ui/controls/materials/outlinedbutton_control.rb +66 -0
  96. data/lib/ruflet_ui/ruflet/ui/controls/materials/outlinediconbutton_control.rb +81 -0
  97. data/lib/ruflet_ui/ruflet/ui/controls/materials/popupmenubutton_control.rb +74 -0
  98. data/lib/ruflet_ui/ruflet/ui/controls/materials/popupmenuitem_control.rb +38 -0
  99. data/lib/ruflet_ui/ruflet/ui/controls/materials/progressbar_control.rb +64 -0
  100. data/lib/ruflet_ui/ruflet/ui/controls/materials/progressring_control.rb +65 -0
  101. data/lib/ruflet_ui/ruflet/ui/controls/materials/radio_control.rb +70 -0
  102. data/lib/ruflet_ui/ruflet/ui/controls/materials/radiogroup_control.rb +33 -0
  103. data/lib/ruflet_ui/ruflet/ui/controls/materials/rangeslider_control.rb +67 -0
  104. data/lib/ruflet_ui/ruflet/ui/controls/materials/reorderablelistview_control.rb +80 -0
  105. data/lib/ruflet_ui/ruflet/ui/controls/materials/ruflet_controls.rb +252 -0
  106. data/lib/ruflet_ui/ruflet/ui/controls/materials/searchbar_control.rb +94 -0
  107. data/lib/ruflet_ui/ruflet/ui/controls/materials/segment_control.rb +33 -0
  108. data/lib/ruflet_ui/ruflet/ui/controls/materials/segmentedbutton_control.rb +63 -0
  109. data/lib/ruflet_ui/ruflet/ui/controls/materials/selectionarea_control.rb +32 -0
  110. data/lib/ruflet_ui/ruflet/ui/controls/materials/slider_control.rb +76 -0
  111. data/lib/ruflet_ui/ruflet/ui/controls/materials/snackbar_control.rb +51 -0
  112. data/lib/ruflet_ui/ruflet/ui/controls/materials/submenubutton_control.rb +66 -0
  113. data/lib/ruflet_ui/ruflet/ui/controls/materials/switch_control.rb +77 -0
  114. data/lib/ruflet_ui/ruflet/ui/controls/materials/tab_control.rb +35 -0
  115. data/lib/ruflet_ui/ruflet/ui/controls/materials/tabbar_control.rb +77 -0
  116. data/lib/ruflet_ui/ruflet/ui/controls/materials/tabbarview_control.rb +57 -0
  117. data/lib/ruflet_ui/ruflet/ui/controls/materials/tabs_control.rb +59 -0
  118. data/lib/ruflet_ui/ruflet/ui/controls/materials/textbutton_control.rb +66 -0
  119. data/lib/ruflet_ui/ruflet/ui/controls/materials/textfield_control.rb +148 -0
  120. data/lib/ruflet_ui/ruflet/ui/controls/materials/timepicker_control.rb +50 -0
  121. data/lib/ruflet_ui/ruflet/ui/controls/materials/verticaldivider_control.rb +36 -0
  122. data/lib/ruflet_ui/ruflet/ui/controls/materials/video_control.rb +39 -0
  123. data/lib/ruflet_ui/ruflet/ui/controls/materials/webview_control.rb +35 -0
  124. data/lib/ruflet_ui/ruflet/ui/controls/ruflet_controls.rb +447 -0
  125. data/lib/ruflet_ui/ruflet/ui/controls/shared/animatedswitcher_control.rb +59 -0
  126. data/lib/ruflet_ui/ruflet/ui/controls/shared/arc_control.rb +29 -0
  127. data/lib/ruflet_ui/ruflet/ui/controls/shared/autofillgroup_control.rb +32 -0
  128. data/lib/ruflet_ui/ruflet/ui/controls/shared/basepage_control.rb +44 -0
  129. data/lib/ruflet_ui/ruflet/ui/controls/shared/browsercontextmenu_control.rb +21 -0
  130. data/lib/ruflet_ui/ruflet/ui/controls/shared/canvas_control.rb +57 -0
  131. data/lib/ruflet_ui/ruflet/ui/controls/shared/circle_control.rb +25 -0
  132. data/lib/ruflet_ui/ruflet/ui/controls/shared/color_control.rb +23 -0
  133. data/lib/ruflet_ui/ruflet/ui/controls/shared/column_control.rb +67 -0
  134. data/lib/ruflet_ui/ruflet/ui/controls/shared/dialogs_control.rb +22 -0
  135. data/lib/ruflet_ui/ruflet/ui/controls/shared/dismissible_control.rb +66 -0
  136. data/lib/ruflet_ui/ruflet/ui/controls/shared/draggable_control.rb +39 -0
  137. data/lib/ruflet_ui/ruflet/ui/controls/shared/dragtarget_control.rb +36 -0
  138. data/lib/ruflet_ui/ruflet/ui/controls/shared/fill_control.rb +22 -0
  139. data/lib/ruflet_ui/ruflet/ui/controls/shared/fletapp_control.rb +62 -0
  140. data/lib/ruflet_ui/ruflet/ui/controls/shared/gesturedetector_control.rb +129 -0
  141. data/lib/ruflet_ui/ruflet/ui/controls/shared/gridview_control.rb +71 -0
  142. data/lib/ruflet_ui/ruflet/ui/controls/shared/hero_control.rb +56 -0
  143. data/lib/ruflet_ui/ruflet/ui/controls/shared/icon_control.rb +64 -0
  144. data/lib/ruflet_ui/ruflet/ui/controls/shared/image_control.rb +27 -0
  145. data/lib/ruflet_ui/ruflet/ui/controls/shared/interactiveviewer_control.rb +69 -0
  146. data/lib/ruflet_ui/ruflet/ui/controls/shared/keyboardlistener_control.rb +36 -0
  147. data/lib/ruflet_ui/ruflet/ui/controls/shared/line_control.rb +26 -0
  148. data/lib/ruflet_ui/ruflet/ui/controls/shared/listview_control.rb +71 -0
  149. data/lib/ruflet_ui/ruflet/ui/controls/shared/markdown_control.rb +70 -0
  150. data/lib/ruflet_ui/ruflet/ui/controls/shared/mergesemantics_control.rb +31 -0
  151. data/lib/ruflet_ui/ruflet/ui/controls/shared/oval_control.rb +26 -0
  152. data/lib/ruflet_ui/ruflet/ui/controls/shared/overlay_control.rb +22 -0
  153. data/lib/ruflet_ui/ruflet/ui/controls/shared/page_control.rb +74 -0
  154. data/lib/ruflet_ui/ruflet/ui/controls/shared/pagelet_control.rb +64 -0
  155. data/lib/ruflet_ui/ruflet/ui/controls/shared/pageview_control.rb +64 -0
  156. data/lib/ruflet_ui/ruflet/ui/controls/shared/path_control.rb +23 -0
  157. data/lib/ruflet_ui/ruflet/ui/controls/shared/placeholder_control.rb +58 -0
  158. data/lib/ruflet_ui/ruflet/ui/controls/shared/points_control.rb +24 -0
  159. data/lib/ruflet_ui/ruflet/ui/controls/shared/rect_control.rb +27 -0
  160. data/lib/ruflet_ui/ruflet/ui/controls/shared/reorderabledraghandle_control.rb +56 -0
  161. data/lib/ruflet_ui/ruflet/ui/controls/shared/responsiverow_control.rb +61 -0
  162. data/lib/ruflet_ui/ruflet/ui/controls/shared/row_control.rb +67 -0
  163. data/lib/ruflet_ui/ruflet/ui/controls/shared/ruflet_controls.rb +140 -0
  164. data/lib/ruflet_ui/ruflet/ui/controls/shared/safearea_control.rb +61 -0
  165. data/lib/ruflet_ui/ruflet/ui/controls/shared/semantics_control.rb +79 -0
  166. data/lib/ruflet_ui/ruflet/ui/controls/shared/serviceregistry_control.rb +21 -0
  167. data/lib/ruflet_ui/ruflet/ui/controls/shared/shadermask_control.rb +57 -0
  168. data/lib/ruflet_ui/ruflet/ui/controls/shared/shadow_control.rb +25 -0
  169. data/lib/ruflet_ui/ruflet/ui/controls/shared/shimmer_control.rb +60 -0
  170. data/lib/ruflet_ui/ruflet/ui/controls/shared/stack_control.rb +58 -0
  171. data/lib/ruflet_ui/ruflet/ui/controls/shared/text_control.rb +32 -0
  172. data/lib/ruflet_ui/ruflet/ui/controls/shared/textspan_control.rb +39 -0
  173. data/lib/ruflet_ui/ruflet/ui/controls/shared/transparentpointer_control.rb +54 -0
  174. data/lib/ruflet_ui/ruflet/ui/controls/shared/view_control.rb +77 -0
  175. data/lib/ruflet_ui/ruflet/ui/controls/shared/window_control.rb +56 -0
  176. data/lib/ruflet_ui/ruflet/ui/controls/shared/windowdragarea_control.rb +58 -0
  177. data/lib/ruflet_ui/ruflet/ui/cupertino_control_factory.rb +13 -0
  178. data/lib/ruflet_ui/ruflet/ui/cupertino_control_methods.rb +26 -0
  179. data/lib/ruflet_ui/ruflet/ui/cupertino_control_registry.rb +49 -0
  180. data/lib/ruflet_ui/ruflet/ui/material_control_factory.rb +13 -0
  181. data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +170 -0
  182. data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +168 -0
  183. data/lib/ruflet_ui/ruflet/ui/services/ruflet/accelerometer_control.rb +26 -0
  184. data/lib/ruflet_ui/ruflet/ui/services/ruflet/barometer_control.rb +26 -0
  185. data/lib/ruflet_ui/ruflet/ui/services/ruflet/battery_control.rb +22 -0
  186. data/lib/ruflet_ui/ruflet/ui/services/ruflet/camera_control.rb +58 -0
  187. data/lib/ruflet_ui/ruflet/ui/services/ruflet/clipboard_control.rb +21 -0
  188. data/lib/ruflet_ui/ruflet/ui/services/ruflet/connectivity_control.rb +22 -0
  189. data/lib/ruflet_ui/ruflet/ui/services/ruflet/filepicker_control.rb +23 -0
  190. data/lib/ruflet_ui/ruflet/ui/services/ruflet/flashlight_control.rb +22 -0
  191. data/lib/ruflet_ui/ruflet/ui/services/ruflet/gyroscope_control.rb +26 -0
  192. data/lib/ruflet_ui/ruflet/ui/services/ruflet/hapticfeedback_control.rb +21 -0
  193. data/lib/ruflet_ui/ruflet/ui/services/ruflet/magnetometer_control.rb +26 -0
  194. data/lib/ruflet_ui/ruflet/ui/services/ruflet/screenbrightness_control.rb +23 -0
  195. data/lib/ruflet_ui/ruflet/ui/services/ruflet/screenshot_control.rb +31 -0
  196. data/lib/ruflet_ui/ruflet/ui/services/ruflet/semanticsservice_control.rb +21 -0
  197. data/lib/ruflet_ui/ruflet/ui/services/ruflet/shakedetector_control.rb +26 -0
  198. data/lib/ruflet_ui/ruflet/ui/services/ruflet/share_control.rb +21 -0
  199. data/lib/ruflet_ui/ruflet/ui/services/ruflet/sharedpreferences_control.rb +21 -0
  200. data/lib/ruflet_ui/ruflet/ui/services/ruflet/storagepaths_control.rb +21 -0
  201. data/lib/ruflet_ui/ruflet/ui/services/ruflet/urllauncher_control.rb +21 -0
  202. data/lib/ruflet_ui/ruflet/ui/services/ruflet/useraccelerometer_control.rb +26 -0
  203. data/lib/ruflet_ui/ruflet/ui/services/ruflet/wakelock_control.rb +21 -0
  204. data/lib/ruflet_ui/ruflet/ui/services/ruflet_services.rb +66 -0
  205. data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +129 -0
  206. data/lib/ruflet_ui/ruflet/ui/widget_builder.rb +64 -0
  207. data/lib/ruflet_ui.rb +160 -0
  208. metadata +245 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 261081fe6de16011831ffa9ccce2ce123ea5c0b078177b9450800df70780cc62
4
+ data.tar.gz: 76d310dd1e0464545ce6172c2ddf8529c24543e1a34b346f02161542e56cb48f
5
+ SHA512:
6
+ metadata.gz: 705e39c75cd934fde6e282ebbf6f8ca26c93f0f96f85dcdae6f227c1343af92a78435b725c6c9d32930a815348875ccf228377cccda569cb96a24f218e9e38f7
7
+ data.tar.gz: 4c24b89490f9cb4a18f198163796b9a156ac9a24dec897c0267c52e6812ab072b0c8889cc5fb4018c2c77ec40d8ed0f7bd79b638050bd76ad1706d3a33885916
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # ruflet
2
+
3
+ Part of Ruflet monorepo.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruflet
4
+ VERSION = "0.0.9" unless const_defined?(:VERSION)
5
+ end
data/lib/ruflet.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ruflet_core"
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thread"
4
+ require "ruflet_protocol"
5
+ require "ruflet_ui"
6
+
7
+ module Ruflet
8
+ @run_interceptors = []
9
+ @run_interceptors_mutex = Mutex.new
10
+
11
+ module_function
12
+
13
+ def run(entrypoint = nil, host: "0.0.0.0", port: 8550, &block)
14
+ callback = entrypoint || block
15
+ raise ArgumentError, "Ruflet.run requires a callable entrypoint or block" unless callback.respond_to?(:call)
16
+
17
+ interceptor = @run_interceptors_mutex.synchronize { @run_interceptors.last }
18
+ if interceptor
19
+ result = interceptor.call(entrypoint: callback, host: host, port: port)
20
+ return result unless result == :pass
21
+ end
22
+
23
+ begin
24
+ require "ruflet_server"
25
+ rescue LoadError => e
26
+ raise LoadError, "Ruflet.run requires the 'ruflet_server' gem unless a run interceptor handles execution.", e.backtrace
27
+ end
28
+
29
+ Server.new(host: host, port: port) do |page|
30
+ callback.call(page)
31
+ end.start
32
+ end
33
+
34
+ def with_run_interceptor(interceptor)
35
+ @run_interceptors_mutex.synchronize { @run_interceptors << interceptor }
36
+ yield
37
+ ensure
38
+ @run_interceptors_mutex.synchronize { @run_interceptors.delete(interceptor) }
39
+ end
40
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruflet
4
+ module Protocol
5
+ ACTIONS = {
6
+ register_client: 1,
7
+ patch_control: 2,
8
+ control_event: 3,
9
+ update_control: 4,
10
+ invoke_control_method: 5,
11
+ session_crashed: 6,
12
+
13
+ # Legacy JSON protocol aliases kept for compatibility.
14
+ register_web_client: "registerWebClient",
15
+ page_event_from_web: "pageEventFromWeb",
16
+ update_control_props: "updateControlProps"
17
+ }.freeze
18
+
19
+ module_function
20
+
21
+ def pack_message(action:, payload:)
22
+ [action, payload]
23
+ end
24
+
25
+ def normalize_register_payload(payload)
26
+ page = payload["page"] || {}
27
+ {
28
+ "session_id" => payload["session_id"],
29
+ "page_name" => payload["page_name"] || "",
30
+ "route" => page["route"] || "/",
31
+ "width" => page["width"],
32
+ "height" => page["height"],
33
+ "platform" => page["platform"],
34
+ "platform_brightness" => page["platform_brightness"],
35
+ "media" => page["media"] || {}
36
+ }
37
+ end
38
+
39
+ def normalize_control_event_payload(payload)
40
+ {
41
+ "target" => payload["target"] || payload["eventTarget"],
42
+ "name" => payload["name"] || payload["eventName"],
43
+ "data" => payload["data"] || payload["eventData"]
44
+ }
45
+ end
46
+
47
+ def normalize_update_control_payload(payload)
48
+ {
49
+ "id" => payload["id"] || payload["target"] || payload["eventTarget"],
50
+ "props" => payload["props"].is_a?(Hash) ? payload["props"] : {}
51
+ }
52
+ end
53
+
54
+ def register_response(session_id:)
55
+ {
56
+ "session_id" => session_id,
57
+ "page_patch" => {},
58
+ "error" => nil
59
+ }
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "ruflet/version"
4
+ require_relative "ruflet_protocol/ruflet/protocol"
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruflet
4
+ class App
5
+ def initialize(host: nil, port: nil)
6
+ @host = (host || ENV["RUFLET_HOST"] || "0.0.0.0")
7
+ @port = normalize_port(port || ENV["RUFLET_PORT"] || 8550)
8
+ end
9
+
10
+ def run
11
+ Ruflet.run(host: @host, port: @port) do |page|
12
+ view(page)
13
+ end
14
+ end
15
+
16
+ def view(_page)
17
+ raise NotImplementedError, "#{self.class} must implement #view(page)"
18
+ end
19
+
20
+ private
21
+
22
+ def normalize_port(value)
23
+ port = value.to_i
24
+ port > 0 ? port : 8550
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,234 @@
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
@@ -0,0 +1,281 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "securerandom"
5
+ rescue LoadError
6
+ nil
7
+ end
8
+ require_relative "icon_data"
9
+ require_relative "icons/material_icon_lookup"
10
+ require_relative "icons/cupertino_icon_lookup"
11
+ require "set"
12
+
13
+ module Ruflet
14
+ class Control
15
+ HOST_EXPANDED_TYPES = %w[view row column].freeze
16
+
17
+ attr_reader :type, :id, :props, :children
18
+ attr_accessor :wire_id, :runtime_page
19
+
20
+ def initialize(type:, id: nil, **props)
21
+ @type = type.to_s.downcase
22
+ @id = (id || props.delete(:id) || "ctrl_#{self.class.generate_id}").to_s
23
+ @children = []
24
+ @handlers = {}
25
+ @wire_id = nil
26
+ @props = normalize_props(extract_handlers(preprocess_props(props)))
27
+ end
28
+
29
+ def on(event_name, &block)
30
+ name = normalized_event_name(event_name)
31
+ validate_event_name!(name)
32
+ @handlers[name] = block
33
+ @props["on_#{name}"] = true
34
+ runtime_page&.update(self, "on_#{name}": true) if wire_id
35
+ self
36
+ end
37
+
38
+ def emit(event_name, event)
39
+ handler = @handlers[normalized_event_name(event_name)]
40
+ return false unless handler
41
+
42
+ handler.call(event)
43
+ true
44
+ end
45
+
46
+ def has_handler?(event_name)
47
+ @handlers.key?(normalized_event_name(event_name))
48
+ end
49
+
50
+ def to_patch
51
+ wire_type = schema_wire_type_for_class
52
+ if wire_type.nil?
53
+ compact_type_key = type.delete("_")
54
+ wire_type = type_map[type] || type_map[compact_type_key]
55
+ end
56
+ raise ArgumentError, "Unknown control type: #{type}" unless wire_type
57
+ patch = {
58
+ "_c" => wire_type,
59
+ "_i" => wire_id
60
+ }
61
+
62
+ internals = {}
63
+ internals["host_positioned"] = true if type == "stack"
64
+ internals["host_expanded"] = true if HOST_EXPANDED_TYPES.include?(type)
65
+ patch["_internals"] = internals unless internals.empty?
66
+
67
+ props.each { |k, v| patch[k] = serialize_value(v) }
68
+ patch["controls"] = children.map(&:to_patch) unless children.empty?
69
+ patch
70
+ end
71
+
72
+ private
73
+
74
+ class << self
75
+ def generate_id
76
+ if defined?(SecureRandom) && SecureRandom.respond_to?(:hex)
77
+ SecureRandom.hex(4)
78
+ else
79
+ format("%08x", rand(0..0xffff_ffff))
80
+ end
81
+ end
82
+ end
83
+
84
+ def serialize_value(value)
85
+ case value
86
+ when Control
87
+ value.to_patch
88
+ when Ruflet::IconData
89
+ value.value
90
+ when Array
91
+ value.map { |v| serialize_value(v) }
92
+ when Hash
93
+ value.transform_values { |v| serialize_value(v) }
94
+ else
95
+ value.respond_to?(:to_h) ? serialize_value(value.to_h) : value
96
+ end
97
+ end
98
+
99
+ def extract_handlers(input)
100
+ output = input.dup
101
+ allowed_events = event_names
102
+ allowed_events_set = allowed_events.to_set
103
+
104
+ output.keys.each do |key|
105
+ key_string = key.to_s
106
+ next unless key_string.start_with?("on_")
107
+
108
+ event_name = normalized_event_name(key_string)
109
+ if allowed_events.any? && !allowed_events_set.include?(event_name)
110
+ raise ArgumentError, "Unknown event `#{key_string}` for control type `#{type}`"
111
+ end
112
+
113
+ handler = output.delete(key)
114
+ @handlers[event_name] = handler if handler.respond_to?(:call)
115
+ output["on_#{event_name}"] = true
116
+ end
117
+
118
+ event_props.each do |prop, event_name|
119
+ string_prop = prop.to_s
120
+ next unless output.key?(prop) || output.key?(string_prop)
121
+ next if allowed_events.any? && !allowed_events_set.include?(event_name)
122
+
123
+ handler = output.key?(prop) ? output.delete(prop) : output.delete(string_prop)
124
+ @handlers[event_name] = handler if handler.respond_to?(:call)
125
+ output["on_#{event_name}"] = true
126
+ end
127
+
128
+ output
129
+ end
130
+
131
+ def normalize_props(hash)
132
+ allowed_props = property_names
133
+ normalized_allowed = allowed_props.to_set
134
+
135
+ hash.each_with_object({}) do |(k, v), result|
136
+ key = k.to_s
137
+ mapped_key = key
138
+ if strict_schema_enforced?(allowed_props) &&
139
+ !mapped_key.start_with?("_") &&
140
+ !mapped_key.start_with?("on_") &&
141
+ !normalized_allowed.include?(mapped_key)
142
+ raise ArgumentError, "Unknown attribute `#{mapped_key}` for control type `#{type}`"
143
+ end
144
+
145
+ value =
146
+ if v.is_a?(Symbol)
147
+ v.to_s
148
+ elsif v.is_a?(Ruflet::IconData)
149
+ v.value
150
+ else
151
+ v
152
+ end
153
+ value = normalize_icon_prop(mapped_key, value)
154
+ value = normalize_color_prop(mapped_key, value)
155
+
156
+ result[mapped_key] = value
157
+ end
158
+ end
159
+
160
+ def preprocess_props(props)
161
+ props
162
+ end
163
+
164
+ def normalize_color_prop(key, value)
165
+ return value unless value.is_a?(String)
166
+ return value.downcase if color_prop_key?(key)
167
+
168
+ value
169
+ end
170
+
171
+ def color_prop_key?(key)
172
+ key == "color" || key == "bgcolor" || key.end_with?("_color")
173
+ end
174
+
175
+ def normalize_icon_prop(key, value)
176
+ return value unless icon_prop_key?(key)
177
+ codepoint = resolve_icon_codepoint(value)
178
+ codepoint.nil? ? value : codepoint
179
+ end
180
+
181
+ def icon_prop_key?(key)
182
+ key == "icon" || key.end_with?("_icon")
183
+ end
184
+
185
+ def resolve_icon_codepoint(value)
186
+ return nil unless value.is_a?(Integer) || value.is_a?(Symbol) || value.is_a?(String)
187
+
188
+ codepoint = Ruflet::MaterialIconLookup.codepoint_for(value)
189
+ if codepoint.nil? || (value.is_a?(Integer) && codepoint == value)
190
+ cupertino = Ruflet::CupertinoIconLookup.codepoint_for(value)
191
+ codepoint = cupertino unless cupertino.nil?
192
+ end
193
+ codepoint
194
+ end
195
+
196
+ def normalized_event_name(event_name)
197
+ event_name.to_s.sub(/\Aon_/, "")
198
+ end
199
+
200
+ def validate_event_name!(event_name)
201
+ events = event_names
202
+ return if events.empty? || events.include?(event_name)
203
+
204
+ raise ArgumentError, "Unknown event `on_#{event_name}` for control type `#{type}`"
205
+ end
206
+
207
+ def strict_schema_enforced?(allowed_props)
208
+ !allowed_props.empty?
209
+ end
210
+
211
+ def property_names
212
+ constructor_keywords_for_schema_class
213
+ .reject { |name| name.to_s.start_with?("on_") }
214
+ .map(&:to_s)
215
+ end
216
+
217
+ def event_names
218
+ constructor_keywords_for_schema_class
219
+ .select { |name| name.to_s.start_with?("on_") }
220
+ .map { |name| name.to_s.sub(/\Aon_/, "") }
221
+ end
222
+
223
+ def schema_wire_type_for_class
224
+ return nil unless self.class.const_defined?(:WIRE)
225
+
226
+ self.class::WIRE.to_s
227
+ end
228
+
229
+ def schema_class_for_validation
230
+ if self.class != Ruflet::Control && has_explicit_initialize_keywords?(self.class)
231
+ return self.class
232
+ end
233
+ begin
234
+ require_relative "ui/control_factory"
235
+ mapped = UI::ControlFactory::CLASS_MAP[type]
236
+ return mapped if mapped && has_explicit_initialize_keywords?(mapped)
237
+ rescue LoadError
238
+ nil
239
+ end
240
+
241
+ begin
242
+ require_relative "ui/controls/ruflet_controls"
243
+ mapped = UI::Controls::RufletControls::CLASS_MAP[type]
244
+ return mapped if mapped && has_explicit_initialize_keywords?(mapped)
245
+ rescue LoadError
246
+ nil
247
+ end
248
+
249
+ nil
250
+ end
251
+
252
+ def constructor_keywords_for_schema_class
253
+ schema_class = schema_class_for_validation
254
+ return [] unless schema_class
255
+
256
+ schema_class.instance_method(:initialize).parameters
257
+ .select { |kind, _| kind == :key || kind == :keyreq }
258
+ .map { |_, name| name }
259
+ .reject { |name| name == :id }
260
+ rescue StandardError
261
+ []
262
+ end
263
+
264
+ def has_explicit_initialize_keywords?(klass)
265
+ params = klass.instance_method(:initialize).parameters
266
+ params.any? { |kind, _| kind == :key || kind == :keyreq }
267
+ rescue StandardError
268
+ false
269
+ end
270
+
271
+ def type_map
272
+ require_relative "ui/control_registry"
273
+ UI::ControlRegistry::TYPE_MAP
274
+ end
275
+
276
+ def event_props
277
+ require_relative "ui/control_registry"
278
+ UI::ControlRegistry::EVENT_PROPS
279
+ end
280
+ end
281
+ end