ruflet_core 0.0.16 → 0.0.18

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -18
  3. data/lib/ruflet/version.rb +1 -1
  4. data/lib/ruflet_core.rb +9 -7
  5. data/lib/ruflet_protocol/ruflet/protocol.rb +28 -54
  6. data/lib/ruflet_ui/ruflet/app.rb +1 -1
  7. data/lib/ruflet_ui/ruflet/colors.rb +4 -18
  8. data/lib/ruflet_ui/ruflet/control.rb +65 -63
  9. data/lib/ruflet_ui/ruflet/dsl.rb +10 -3
  10. data/lib/ruflet_ui/ruflet/icons/cupertino/cupertino_icons.rb +2 -2
  11. data/lib/ruflet_ui/ruflet/icons/cupertino_icon_lookup.rb +1 -0
  12. data/lib/ruflet_ui/ruflet/icons/icon_constant_names.rb +29 -0
  13. data/lib/ruflet_ui/ruflet/icons/material/material_icons.rb +2 -2
  14. data/lib/ruflet_ui/ruflet/icons/material_icon_lookup.rb +1 -0
  15. data/lib/ruflet_ui/ruflet/page.rb +303 -460
  16. data/lib/ruflet_ui/ruflet/ui/control_factory.rb +68 -12
  17. data/lib/ruflet_ui/ruflet/ui/control_registry.rb +13 -6
  18. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheet_control.rb +8 -45
  19. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactionsheetaction_control.rb +45 -2
  20. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoactivityindicator_control.rb +43 -2
  21. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoalertdialog_control.rb +0 -5
  22. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinobutton_control.rb +59 -4
  23. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocheckbox_control.rb +56 -1
  24. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenu_control.rb +1 -3
  25. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinocontextmenuaction_control.rb +1 -1
  26. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodatepicker_control.rb +53 -8
  27. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinodialogaction_control.rb +1 -1
  28. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinofilledbutton_control.rb +59 -4
  29. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinolisttile_control.rb +54 -9
  30. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinonavigationbar_control.rb +47 -9
  31. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinopicker_control.rb +52 -10
  32. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoradio_control.rb +52 -1
  33. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinosegmentedbutton_control.rb +49 -1
  34. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslider_control.rb +50 -5
  35. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoslidingsegmentedbutton_control.rb +46 -1
  36. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinoswitch_control.rb +61 -1
  37. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotextfield_control.rb +145 -1
  38. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotimerpicker_control.rb +47 -12
  39. data/lib/ruflet_ui/ruflet/ui/controls/cupertinos/cupertinotintedbutton_control.rb +59 -4
  40. data/lib/ruflet_ui/ruflet/ui/controls/materials/alertdialog_control.rb +8 -45
  41. data/lib/ruflet_ui/ruflet/ui/controls/materials/appbar_control.rb +8 -40
  42. data/lib/ruflet_ui/ruflet/ui/controls/materials/audio_control.rb +16 -5
  43. data/lib/ruflet_ui/ruflet/ui/controls/materials/autocomplete_control.rb +44 -1
  44. data/lib/ruflet_ui/ruflet/ui/controls/materials/badge_control.rb +0 -7
  45. data/lib/ruflet_ui/ruflet/ui/controls/materials/banner_control.rb +0 -7
  46. data/lib/ruflet_ui/ruflet/ui/controls/materials/bottomappbar_control.rb +8 -47
  47. data/lib/ruflet_ui/ruflet/ui/controls/materials/bottomsheet_control.rb +0 -3
  48. data/lib/ruflet_ui/ruflet/ui/controls/materials/button_control.rb +8 -54
  49. data/lib/ruflet_ui/ruflet/ui/controls/materials/card_control.rb +8 -50
  50. data/lib/ruflet_ui/ruflet/ui/controls/materials/chart_controls.rb +19 -0
  51. data/lib/ruflet_ui/ruflet/ui/controls/materials/checkbox_control.rb +9 -60
  52. data/lib/ruflet_ui/ruflet/ui/controls/materials/chip_control.rb +7 -81
  53. data/lib/ruflet_ui/ruflet/ui/controls/materials/circleavatar_control.rb +7 -56
  54. data/lib/ruflet_ui/ruflet/ui/controls/materials/container_control.rb +9 -65
  55. data/lib/ruflet_ui/ruflet/ui/controls/materials/contextmenu_control.rb +50 -4
  56. data/lib/ruflet_ui/ruflet/ui/controls/materials/datacell_control.rb +1 -3
  57. data/lib/ruflet_ui/ruflet/ui/controls/materials/datacolumn_control.rb +1 -3
  58. data/lib/ruflet_ui/ruflet/ui/controls/materials/datatable_control.rb +7 -88
  59. data/lib/ruflet_ui/ruflet/ui/controls/materials/datepicker_control.rb +9 -55
  60. data/lib/ruflet_ui/ruflet/ui/controls/materials/daterangepicker_control.rb +8 -58
  61. data/lib/ruflet_ui/ruflet/ui/controls/materials/divider_control.rb +0 -9
  62. data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdown_control.rb +8 -93
  63. data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdownm2_control.rb +9 -103
  64. data/lib/ruflet_ui/ruflet/ui/controls/materials/dropdownoption_control.rb +0 -2
  65. data/lib/ruflet_ui/ruflet/ui/controls/materials/expansionpanel_control.rb +7 -51
  66. data/lib/ruflet_ui/ruflet/ui/controls/materials/expansionpanellist_control.rb +46 -5
  67. data/lib/ruflet_ui/ruflet/ui/controls/materials/expansiontile_control.rb +69 -3
  68. data/lib/ruflet_ui/ruflet/ui/controls/materials/filledbutton_control.rb +54 -2
  69. data/lib/ruflet_ui/ruflet/ui/controls/materials/fillediconbutton_control.rb +67 -5
  70. data/lib/ruflet_ui/ruflet/ui/controls/materials/filledtonalbutton_control.rb +54 -2
  71. data/lib/ruflet_ui/ruflet/ui/controls/materials/filledtonaliconbutton_control.rb +67 -5
  72. data/lib/ruflet_ui/ruflet/ui/controls/materials/floatingactionbutton_control.rb +7 -69
  73. data/lib/ruflet_ui/ruflet/ui/controls/materials/iconbutton_control.rb +8 -68
  74. data/lib/ruflet_ui/ruflet/ui/controls/materials/listtile_control.rb +8 -74
  75. data/lib/ruflet_ui/ruflet/ui/controls/materials/map_control.rb +99 -0
  76. data/lib/ruflet_ui/ruflet/ui/controls/materials/menuitembutton_control.rb +8 -56
  77. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationbar_control.rb +7 -59
  78. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationdrawer_control.rb +0 -7
  79. data/lib/ruflet_ui/ruflet/ui/controls/materials/navigationrail_control.rb +7 -73
  80. data/lib/ruflet_ui/ruflet/ui/controls/materials/outlinedbutton_control.rb +51 -2
  81. data/lib/ruflet_ui/ruflet/ui/controls/materials/outlinediconbutton_control.rb +67 -5
  82. data/lib/ruflet_ui/ruflet/ui/controls/materials/popupmenubutton_control.rb +8 -61
  83. data/lib/ruflet_ui/ruflet/ui/controls/materials/popupmenuitem_control.rb +0 -6
  84. data/lib/ruflet_ui/ruflet/ui/controls/materials/progressbar_control.rb +8 -56
  85. data/lib/ruflet_ui/ruflet/ui/controls/materials/progressring_control.rb +8 -56
  86. data/lib/ruflet_ui/ruflet/ui/controls/materials/radio_control.rb +9 -54
  87. data/lib/ruflet_ui/ruflet/ui/controls/materials/rangeslider_control.rb +7 -62
  88. data/lib/ruflet_ui/ruflet/ui/controls/materials/reorderablelistview_control.rb +9 -64
  89. data/lib/ruflet_ui/ruflet/ui/controls/materials/ruflet_controls.rb +5 -26
  90. data/lib/ruflet_ui/ruflet/ui/controls/materials/searchbar_control.rb +80 -11
  91. data/lib/ruflet_ui/ruflet/ui/controls/materials/segment_control.rb +0 -3
  92. data/lib/ruflet_ui/ruflet/ui/controls/materials/segmentedbutton_control.rb +7 -64
  93. data/lib/ruflet_ui/ruflet/ui/controls/materials/selectionarea_control.rb +1 -3
  94. data/lib/ruflet_ui/ruflet/ui/controls/materials/slider_control.rb +9 -60
  95. data/lib/ruflet_ui/ruflet/ui/controls/materials/snackbar_control.rb +37 -4
  96. data/lib/ruflet_ui/ruflet/ui/controls/materials/snackbaraction_control.rb +38 -0
  97. data/lib/ruflet_ui/ruflet/ui/controls/materials/spinkit_control.rb +25 -0
  98. data/lib/ruflet_ui/ruflet/ui/controls/materials/submenubutton_control.rb +52 -7
  99. data/lib/ruflet_ui/ruflet/ui/controls/materials/switch_control.rb +9 -61
  100. data/lib/ruflet_ui/ruflet/ui/controls/materials/tab_control.rb +0 -7
  101. data/lib/ruflet_ui/ruflet/ui/controls/materials/tabbar_control.rb +8 -64
  102. data/lib/ruflet_ui/ruflet/ui/controls/materials/tabbarview_control.rb +43 -5
  103. data/lib/ruflet_ui/ruflet/ui/controls/materials/tabs_control.rb +7 -47
  104. data/lib/ruflet_ui/ruflet/ui/controls/materials/textbutton_control.rb +51 -2
  105. data/lib/ruflet_ui/ruflet/ui/controls/materials/textfield_control.rb +9 -132
  106. data/lib/ruflet_ui/ruflet/ui/controls/materials/timepicker_control.rb +10 -34
  107. data/lib/ruflet_ui/ruflet/ui/controls/materials/verticaldivider_control.rb +0 -9
  108. data/lib/ruflet_ui/ruflet/ui/controls/materials/video_control.rb +9 -42
  109. data/lib/ruflet_ui/ruflet/ui/controls/materials/webview_control.rb +1 -114
  110. data/lib/ruflet_ui/ruflet/ui/controls/ruflet_controls.rb +13 -28
  111. data/lib/ruflet_ui/ruflet/ui/controls/shared/animatedswitcher_control.rb +46 -4
  112. data/lib/ruflet_ui/ruflet/ui/controls/shared/arc_control.rb +1 -0
  113. data/lib/ruflet_ui/ruflet/ui/controls/shared/browsercontextmenu_control.rb +1 -12
  114. data/lib/ruflet_ui/ruflet/ui/controls/shared/canvas_control.rb +8 -54
  115. data/lib/ruflet_ui/ruflet/ui/controls/shared/circle_control.rb +1 -0
  116. data/lib/ruflet_ui/ruflet/ui/controls/shared/column_control.rb +9 -51
  117. data/lib/ruflet_ui/ruflet/ui/controls/shared/dismissible_control.rb +52 -12
  118. data/lib/ruflet_ui/ruflet/ui/controls/shared/draggable_control.rb +1 -7
  119. data/lib/ruflet_ui/ruflet/ui/controls/shared/dragtarget_control.rb +1 -3
  120. data/lib/ruflet_ui/ruflet/ui/controls/shared/fletapp_control.rb +9 -46
  121. data/lib/ruflet_ui/ruflet/ui/controls/shared/gesturedetector_control.rb +9 -113
  122. data/lib/ruflet_ui/ruflet/ui/controls/shared/gridview_control.rb +57 -13
  123. data/lib/ruflet_ui/ruflet/ui/controls/shared/hero_control.rb +9 -40
  124. data/lib/ruflet_ui/ruflet/ui/controls/shared/icon_control.rb +9 -48
  125. data/lib/ruflet_ui/ruflet/ui/controls/shared/interactiveviewer_control.rb +9 -53
  126. data/lib/ruflet_ui/ruflet/ui/controls/shared/line_control.rb +1 -0
  127. data/lib/ruflet_ui/ruflet/ui/controls/shared/listview_control.rb +57 -11
  128. data/lib/ruflet_ui/ruflet/ui/controls/shared/markdown_control.rb +9 -54
  129. data/lib/ruflet_ui/ruflet/ui/controls/shared/oval_control.rb +1 -0
  130. data/lib/ruflet_ui/ruflet/ui/controls/shared/page_control.rb +9 -58
  131. data/lib/ruflet_ui/ruflet/ui/controls/shared/pagelet_control.rb +9 -48
  132. data/lib/ruflet_ui/ruflet/ui/controls/shared/pageview_control.rb +50 -4
  133. data/lib/ruflet_ui/ruflet/ui/controls/shared/path_control.rb +1 -0
  134. data/lib/ruflet_ui/ruflet/ui/controls/shared/placeholder_control.rb +44 -9
  135. data/lib/ruflet_ui/ruflet/ui/controls/shared/points_control.rb +1 -0
  136. data/lib/ruflet_ui/ruflet/ui/controls/shared/rect_control.rb +1 -0
  137. data/lib/ruflet_ui/ruflet/ui/controls/shared/reorderabledraghandle_control.rb +43 -4
  138. data/lib/ruflet_ui/ruflet/ui/controls/shared/responsiverow_control.rb +47 -15
  139. data/lib/ruflet_ui/ruflet/ui/controls/shared/rotatedbox_control.rb +97 -0
  140. data/lib/ruflet_ui/ruflet/ui/controls/shared/row_control.rb +9 -51
  141. data/lib/ruflet_ui/ruflet/ui/controls/shared/ruflet_controls.rb +5 -0
  142. data/lib/ruflet_ui/ruflet/ui/controls/shared/safearea_control.rb +48 -4
  143. data/lib/ruflet_ui/ruflet/ui/{services/ruflet → controls/shared}/screenshot_control.rb +18 -2
  144. data/lib/ruflet_ui/ruflet/ui/controls/shared/semantics_control.rb +65 -1
  145. data/lib/ruflet_ui/ruflet/ui/controls/shared/shadermask_control.rb +9 -41
  146. data/lib/ruflet_ui/ruflet/ui/controls/shared/shimmer_control.rb +9 -44
  147. data/lib/ruflet_ui/ruflet/ui/controls/shared/stack_control.rb +44 -1
  148. data/lib/ruflet_ui/ruflet/ui/controls/shared/text_control.rb +9 -35
  149. data/lib/ruflet_ui/ruflet/ui/controls/shared/transparentpointer_control.rb +9 -38
  150. data/lib/ruflet_ui/ruflet/ui/controls/shared/view_control.rb +63 -1
  151. data/lib/ruflet_ui/ruflet/ui/controls/shared/window_control.rb +40 -66
  152. data/lib/ruflet_ui/ruflet/ui/controls/shared/windowdragarea_control.rb +45 -4
  153. data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +61 -17
  154. data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +22 -0
  155. data/lib/ruflet_ui/ruflet/ui/services/ruflet/accelerometer_control.rb +1 -0
  156. data/lib/ruflet_ui/ruflet/ui/services/ruflet/audio_recorder_control.rb +14 -36
  157. data/lib/ruflet_ui/ruflet/ui/services/ruflet/barometer_control.rb +1 -0
  158. data/lib/ruflet_ui/ruflet/ui/services/ruflet/battery_control.rb +1 -0
  159. data/lib/ruflet_ui/ruflet/ui/services/ruflet/camera_control.rb +9 -42
  160. data/lib/ruflet_ui/ruflet/ui/services/ruflet/clipboard_control.rb +31 -0
  161. data/lib/ruflet_ui/ruflet/ui/services/ruflet/connectivity_control.rb +1 -0
  162. data/lib/ruflet_ui/ruflet/ui/services/ruflet/filepicker_control.rb +1 -0
  163. data/lib/ruflet_ui/ruflet/ui/services/ruflet/flashlight_control.rb +1 -0
  164. data/lib/ruflet_ui/ruflet/ui/services/ruflet/geolocator_control.rb +14 -30
  165. data/lib/ruflet_ui/ruflet/ui/services/ruflet/gyroscope_control.rb +1 -0
  166. data/lib/ruflet_ui/ruflet/ui/services/ruflet/hapticfeedback_control.rb +1 -0
  167. data/lib/ruflet_ui/ruflet/ui/services/ruflet/magnetometer_control.rb +1 -0
  168. data/lib/ruflet_ui/ruflet/ui/services/ruflet/permissionhandler_control.rb +5 -20
  169. data/lib/ruflet_ui/ruflet/ui/services/ruflet/screenbrightness_control.rb +1 -0
  170. data/lib/ruflet_ui/ruflet/ui/services/ruflet/securestorage_control.rb +22 -49
  171. data/lib/ruflet_ui/ruflet/ui/services/ruflet/semanticsservice_control.rb +20 -15
  172. data/lib/ruflet_ui/ruflet/ui/services/ruflet/shakedetector_control.rb +1 -0
  173. data/lib/ruflet_ui/ruflet/ui/services/ruflet/share_control.rb +1 -0
  174. data/lib/ruflet_ui/ruflet/ui/services/ruflet/sharedpreferences_control.rb +1 -0
  175. data/lib/ruflet_ui/ruflet/ui/services/ruflet/storagepaths_control.rb +1 -0
  176. data/lib/ruflet_ui/ruflet/ui/services/ruflet/urllauncher_control.rb +1 -0
  177. data/lib/ruflet_ui/ruflet/ui/services/ruflet/useraccelerometer_control.rb +1 -0
  178. data/lib/ruflet_ui/ruflet/ui/services/ruflet/wakelock_control.rb +1 -0
  179. data/lib/ruflet_ui/ruflet/ui/services/ruflet_services.rb +0 -7
  180. data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +20 -1
  181. data/lib/ruflet_ui.rb +12 -10
  182. metadata +8 -9
  183. data/lib/ruflet_ui/ruflet/types/animation.rb +0 -110
  184. data/lib/ruflet_ui/ruflet/ui/controls/materials/codeeditor_control.rb +0 -93
  185. data/lib/ruflet_ui/ruflet/ui/controls/materials/map_controls.rb +0 -311
  186. data/lib/ruflet_ui/ruflet/ui/controls/materials/rive_control.rb +0 -87
  187. data/lib/ruflet_ui/ruflet/ui/controls/materials/spinkit_controls.rb +0 -109
  188. data/lib/ruflet_ui/ruflet/ui/services/ruflet/tester_control.rb +0 -126
@@ -10,9 +10,30 @@ module Ruflet
10
10
  module_function
11
11
 
12
12
  CLASS_MAP =
13
- Controls::RufletControls::CLASS_MAP
14
- .merge(Services::RufletServices::CLASS_MAP)
13
+ Services::RufletServices::CLASS_MAP
14
+ .merge(Controls::RufletControls::CLASS_MAP)
15
15
  .freeze
16
+ CONSTRUCTOR_KEYWORDS_CACHE = {}
17
+
18
+ PYTHON_COMMON_ATTRIBUTES = %i[flip ref transform].freeze
19
+ PYTHON_ATTRIBUTE_OVERRIDES = {
20
+ "expansionpanellist" => %i[auto_scroll on_scroll scroll scroll_interval],
21
+ "fletapp" => %i[assets_dir on_python_output],
22
+ "image" => %i[
23
+ align animate_align animate_margin animate_offset animate_opacity animate_position
24
+ animate_rotation animate_scale animate_size aspect_ratio badge bottom col disabled
25
+ expand expand_loose left margin offset on_animation_end on_size_change opacity right
26
+ rotate rtl scale size_change_interval tooltip top visible
27
+ ],
28
+ "navigationrail" => %i[pin_leading_to_top pin_trailing_to_bottom scrollable],
29
+ "responsiverow" => %i[auto_scroll on_scroll scroll scroll_interval],
30
+ "text" => %i[
31
+ align animate_align animate_margin animate_offset animate_opacity animate_position
32
+ animate_rotation animate_scale animate_size aspect_ratio badge bottom col disabled
33
+ expand expand_loose height left margin offset on_animation_end on_size_change opacity
34
+ right rtl scale size_change_interval tooltip top visible width
35
+ ]
36
+ }.freeze
16
37
 
17
38
  def build(type, id: nil, **props)
18
39
  normalized_type = type.to_s.downcase
@@ -21,19 +42,29 @@ module Ruflet
21
42
  end
22
43
  klass = CLASS_MAP[normalized_type]
23
44
  if klass
24
- normalized_props = normalize_constructor_props(klass, props)
45
+ normalized_props, supplemental_props = normalize_constructor_props(klass, normalized_type, props)
25
46
  if ENV["RUFLET_DEBUG"] == "1" && normalized_type == "floatingactionbutton"
26
47
  Kernel.warn("[factory] normalized_props=#{normalized_props.inspect}")
27
48
  end
28
- return klass.new(id: id, **normalized_props)
49
+ control = klass.new(id: id, **normalized_props)
50
+ supplemental_props.each do |key, value|
51
+ if key.to_s.start_with?("on_") && value.respond_to?(:call)
52
+ control.attach_handler(key.to_s.delete_prefix("on_"), value)
53
+ next
54
+ end
55
+ next if key == :ref
56
+
57
+ control.props[key.to_s] = normalize_common_value(value)
58
+ end
59
+ return control
29
60
  end
30
61
 
31
- raise ArgumentError, "Unknown control type: #{normalized_type}"
62
+ Control.new(type: normalized_type, id: id, **props)
32
63
  end
33
64
 
34
- def normalize_constructor_props(klass, props)
65
+ def normalize_constructor_props(klass, type, props)
35
66
  keywords = constructor_keywords(klass)
36
- return props if keywords.empty?
67
+ return [props, {}] if keywords.empty? && PYTHON_ATTRIBUTE_OVERRIDES[type].nil?
37
68
 
38
69
  allowed = keywords.map(&:to_s)
39
70
  mapped = props.each_with_object({}) { |(k, v), out| out[k.to_sym] = v }
@@ -43,17 +74,42 @@ module Ruflet
43
74
  if mapped.key?(:value) && !allowed.include?("value") && allowed.include?("text") && !mapped.key?(:text)
44
75
  mapped[:text] = mapped.delete(:value)
45
76
  end
46
- mapped
77
+ supplemental_names = PYTHON_COMMON_ATTRIBUTES + PYTHON_ATTRIBUTE_OVERRIDES.fetch(type, [])
78
+ supplemental = mapped.slice(*supplemental_names)
79
+ [mapped.reject { |key, _| supplemental_names.include?(key) }, supplemental]
47
80
  end
48
81
 
49
82
  def constructor_keywords(klass)
50
- klass.instance_method(:initialize).parameters
51
- .select { |kind, _| kind == :key || kind == :keyreq }
52
- .map { |_, name| name }
53
- .reject { |name| name == :id }
83
+ return CONSTRUCTOR_KEYWORDS_CACHE[klass] if CONSTRUCTOR_KEYWORDS_CACHE.key?(klass)
84
+
85
+ keywords = if klass.const_defined?(:KEYWORDS)
86
+ klass::KEYWORDS
87
+ else
88
+ klass.instance_method(:initialize).parameters
89
+ .select { |kind, _| kind == :key || kind == :keyreq }
90
+ .map { |_, name| name }
91
+ .reject { |name| name == :id }
92
+ end
93
+
94
+ CONSTRUCTOR_KEYWORDS_CACHE[klass] = keywords.freeze
54
95
  rescue StandardError
55
96
  []
56
97
  end
98
+
99
+ def normalize_common_value(value)
100
+ case value
101
+ when Hash
102
+ value.each_with_object({}) do |(key, nested), result|
103
+ result[key.to_s] = normalize_common_value(nested)
104
+ end
105
+ when Array
106
+ value.map { |nested| normalize_common_value(nested) }
107
+ when Symbol
108
+ value.to_s
109
+ else
110
+ value
111
+ end
112
+ end
57
113
  end
58
114
  end
59
115
  end
@@ -14,12 +14,19 @@ module Ruflet
14
14
  .values
15
15
  .uniq
16
16
  .each_with_object({}) do |schema, events|
17
- schema.instance_method(:initialize).parameters
18
- .select { |kind, name| (kind == :key || kind == :keyreq) && name.to_s.start_with?("on_") }
19
- .reject { |_, name| name.to_s.end_with?("_hint_text") }
20
- .each do |_, name|
21
- event_name = name.to_s.sub(/\Aon_/, "")
22
- normalized = event_name.to_s.sub(/\Aon_/, "")
17
+ keywords =
18
+ if schema.const_defined?(:KEYWORDS)
19
+ schema::KEYWORDS
20
+ else
21
+ schema.instance_method(:initialize).parameters
22
+ .select { |kind, _| kind == :key || kind == :keyreq }
23
+ .map { |_, name| name }
24
+ end
25
+ keywords
26
+ .select { |name| name.to_s.start_with?("on_") }
27
+ .reject { |name| name.to_s.end_with?("_hint_text") }
28
+ .each do |name|
29
+ normalized = name.to_s[3..-1]
23
30
  events[:"on_#{normalized}"] = normalized
24
31
  end
25
32
  end
@@ -8,52 +8,15 @@ module Ruflet
8
8
  TYPE = "cupertinoactionsheet".freeze
9
9
  WIRE = "CupertinoActionSheet".freeze
10
10
 
11
- def initialize(id: nil, actions: nil, align: nil, animate_align: nil, animate_margin: nil, animate_offset: nil, animate_opacity: nil, animate_position: nil, animate_rotation: nil, animate_scale: nil, animate_size: nil, aspect_ratio: nil, badge: nil, bottom: nil, cancel: nil, col: nil, data: nil, disabled: nil, expand: nil, expand_loose: nil, height: nil, key: nil, left: nil, margin: nil, message: nil, offset: nil, opacity: nil, right: nil, rotate: nil, rtl: nil, scale: nil, size_change_interval: nil, title: nil, tooltip: nil, top: nil, visible: nil, width: nil, on_animation_end: nil, on_size_change: nil)
12
- visible_actions = Array(actions).reject { |action| hidden_control?(action) }
13
- if visible_actions.empty? && hidden_or_nil?(title) && hidden_or_nil?(message) && hidden_or_nil?(cancel)
14
- raise ArgumentError, "cupertino_action_sheet requires actions, title, message, or cancel"
15
- end
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
16
12
 
17
- props = {}
18
- props[:actions] = actions unless actions.nil?
19
- props[:align] = align unless align.nil?
20
- props[:animate_align] = animate_align unless animate_align.nil?
21
- props[:animate_margin] = animate_margin unless animate_margin.nil?
22
- props[:animate_offset] = animate_offset unless animate_offset.nil?
23
- props[:animate_opacity] = animate_opacity unless animate_opacity.nil?
24
- props[:animate_position] = animate_position unless animate_position.nil?
25
- props[:animate_rotation] = animate_rotation unless animate_rotation.nil?
26
- props[:animate_scale] = animate_scale unless animate_scale.nil?
27
- props[:animate_size] = animate_size unless animate_size.nil?
28
- props[:aspect_ratio] = aspect_ratio unless aspect_ratio.nil?
29
- props[:badge] = badge unless badge.nil?
30
- props[:bottom] = bottom unless bottom.nil?
31
- props[:cancel] = cancel unless cancel.nil?
32
- props[:col] = col unless col.nil?
33
- props[:data] = data unless data.nil?
34
- props[:disabled] = disabled unless disabled.nil?
35
- props[:expand] = expand unless expand.nil?
36
- props[:expand_loose] = expand_loose unless expand_loose.nil?
37
- props[:height] = height unless height.nil?
38
- props[:key] = key unless key.nil?
39
- props[:left] = left unless left.nil?
40
- props[:margin] = margin unless margin.nil?
41
- props[:message] = message unless message.nil?
42
- props[:offset] = offset unless offset.nil?
43
- props[:opacity] = opacity unless opacity.nil?
44
- props[:right] = right unless right.nil?
45
- props[:rotate] = rotate unless rotate.nil?
46
- props[:rtl] = rtl unless rtl.nil?
47
- props[:scale] = scale unless scale.nil?
48
- props[:size_change_interval] = size_change_interval unless size_change_interval.nil?
49
- props[:title] = title unless title.nil?
50
- props[:tooltip] = tooltip unless tooltip.nil?
51
- props[:top] = top unless top.nil?
52
- props[:visible] = visible unless visible.nil?
53
- props[:width] = width unless width.nil?
54
- props[:on_animation_end] = on_animation_end unless on_animation_end.nil?
55
- props[:on_size_change] = on_size_change unless on_size_change.nil?
56
- super(type: TYPE, id: id, **props)
13
+ def initialize(id: nil, **props)
14
+ compact = {}
15
+ props.each do |key, value|
16
+ raise ArgumentError, "unknown keyword: :#{key}" unless KEYWORDS.include?(key)
17
+ compact[key] = value unless value.nil?
18
+ end
19
+ super(type: TYPE, id: id, **compact)
57
20
  end
58
21
 
59
22
  private
@@ -8,8 +8,51 @@ module Ruflet
8
8
  TYPE = "cupertinoactionsheetaction".freeze
9
9
  WIRE = "CupertinoActionSheetAction".freeze
10
10
 
11
- def initialize(id: nil, align: nil, animate_align: nil, animate_margin: nil, animate_offset: nil, animate_opacity: nil, animate_position: nil, animate_rotation: nil, animate_scale: nil, animate_size: nil, aspect_ratio: nil, badge: nil, bottom: nil, col: nil, content: nil, data: nil, default: nil, destructive: nil, disabled: nil, expand: nil, expand_loose: nil, height: nil, key: nil, left: nil, margin: nil, mouse_cursor: nil, offset: nil, opacity: nil, right: nil, rotate: nil, rtl: nil, scale: nil, size_change_interval: nil, tooltip: nil, top: nil, visible: nil, width: nil, on_animation_end: nil, on_click: nil, on_size_change: nil)
12
- raise ArgumentError, "cupertino_action_sheet_action requires visible content" if content.nil? || (content.respond_to?(:props) && content.props["visible"] == false)
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
+
13
+ def initialize(id: nil, **props)
14
+ unknown = props.keys.reject { |key| KEYWORDS.include?(key) }
15
+ raise ArgumentError, "unknown keywords: #{unknown.join(', ')}" unless unknown.empty?
16
+ align = props[:align]
17
+ animate_align = props[:animate_align]
18
+ animate_margin = props[:animate_margin]
19
+ animate_offset = props[:animate_offset]
20
+ animate_opacity = props[:animate_opacity]
21
+ animate_position = props[:animate_position]
22
+ animate_rotation = props[:animate_rotation]
23
+ animate_scale = props[:animate_scale]
24
+ animate_size = props[:animate_size]
25
+ aspect_ratio = props[:aspect_ratio]
26
+ badge = props[:badge]
27
+ bottom = props[:bottom]
28
+ col = props[:col]
29
+ content = props[:content]
30
+ data = props[:data]
31
+ default = props[:default]
32
+ destructive = props[:destructive]
33
+ disabled = props[:disabled]
34
+ expand = props[:expand]
35
+ expand_loose = props[:expand_loose]
36
+ height = props[:height]
37
+ key = props[:key]
38
+ left = props[:left]
39
+ margin = props[:margin]
40
+ mouse_cursor = props[:mouse_cursor]
41
+ offset = props[:offset]
42
+ opacity = props[:opacity]
43
+ right = props[:right]
44
+ rotate = props[:rotate]
45
+ rtl = props[:rtl]
46
+ scale = props[:scale]
47
+ size_change_interval = props[:size_change_interval]
48
+ tooltip = props[:tooltip]
49
+ top = props[:top]
50
+ visible = props[:visible]
51
+ width = props[:width]
52
+ on_animation_end = props[:on_animation_end]
53
+ on_click = props[:on_click]
54
+ on_size_change = props[:on_size_change]
55
+ raise ArgumentError, "cupertino_action_sheet_action requires content" if content.nil?
13
56
  default = false if default.nil?
14
57
  destructive = false if destructive.nil?
15
58
 
@@ -8,10 +8,51 @@ module Ruflet
8
8
  TYPE = "cupertinoactivityindicator".freeze
9
9
  WIRE = "CupertinoActivityIndicator".freeze
10
10
 
11
- def initialize(id: nil, align: nil, animate_align: nil, animate_margin: nil, animate_offset: nil, animate_opacity: nil, animate_position: nil, animate_rotation: nil, animate_scale: nil, animate_size: nil, animating: nil, aspect_ratio: nil, badge: nil, bottom: nil, col: nil, color: nil, data: nil, disabled: nil, expand: nil, expand_loose: nil, height: nil, key: nil, left: nil, margin: nil, offset: nil, opacity: nil, progress: nil, radius: nil, right: nil, rotate: nil, rtl: nil, scale: nil, size_change_interval: nil, tooltip: nil, top: nil, visible: nil, width: nil, on_animation_end: nil, on_size_change: nil)
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
+
13
+ def initialize(id: nil, **props)
14
+ unknown = props.keys.reject { |key| KEYWORDS.include?(key) }
15
+ raise ArgumentError, "unknown keywords: #{unknown.join(', ')}" unless unknown.empty?
16
+ align = props[:align]
17
+ animate_align = props[:animate_align]
18
+ animate_margin = props[:animate_margin]
19
+ animate_offset = props[:animate_offset]
20
+ animate_opacity = props[:animate_opacity]
21
+ animate_position = props[:animate_position]
22
+ animate_rotation = props[:animate_rotation]
23
+ animate_scale = props[:animate_scale]
24
+ animate_size = props[:animate_size]
25
+ animating = props[:animating]
26
+ aspect_ratio = props[:aspect_ratio]
27
+ badge = props[:badge]
28
+ bottom = props[:bottom]
29
+ col = props[:col]
30
+ color = props[:color]
31
+ data = props[:data]
32
+ disabled = props[:disabled]
33
+ expand = props[:expand]
34
+ expand_loose = props[:expand_loose]
35
+ height = props[:height]
36
+ key = props[:key]
37
+ left = props[:left]
38
+ margin = props[:margin]
39
+ offset = props[:offset]
40
+ opacity = props[:opacity]
41
+ progress = props[:progress]
42
+ radius = props[:radius]
43
+ right = props[:right]
44
+ rotate = props[:rotate]
45
+ rtl = props[:rtl]
46
+ scale = props[:scale]
47
+ size_change_interval = props[:size_change_interval]
48
+ tooltip = props[:tooltip]
49
+ top = props[:top]
50
+ visible = props[:visible]
51
+ width = props[:width]
52
+ on_animation_end = props[:on_animation_end]
53
+ on_size_change = props[:on_size_change]
12
54
  animating = true if animating.nil?
13
55
  radius = 10 if radius.nil?
14
- raise ArgumentError, "cupertino_activity_indicator radius must be greater than 0" unless radius.positive?
15
56
 
16
57
  props = {}
17
58
  props[:align] = align unless align.nil?
@@ -13,11 +13,6 @@ module Ruflet
13
13
  inset_animation = { "duration" => 100, "curve" => "decelerate" } if inset_animation.nil?
14
14
  modal = false if modal.nil?
15
15
 
16
- visible_actions = Array(actions).reject { |action| hidden_control?(action) }
17
- if visible_actions.empty? && hidden_or_nil?(title) && hidden_or_nil?(content)
18
- raise ArgumentError, "cupertino_alert_dialog requires title, content, or actions"
19
- end
20
-
21
16
  props = {}
22
17
  props[:actions] = actions unless actions.nil?
23
18
  props[:adaptive] = adaptive unless adaptive.nil?
@@ -8,15 +8,70 @@ module Ruflet
8
8
  TYPE = "cupertinobutton".freeze
9
9
  WIRE = "CupertinoButton".freeze
10
10
 
11
- def initialize(id: nil, align: nil, alignment: nil, animate_align: nil, animate_margin: nil, animate_offset: nil, animate_opacity: nil, animate_position: nil, animate_rotation: nil, animate_scale: nil, animate_size: nil, aspect_ratio: nil, autofocus: nil, badge: nil, bgcolor: nil, border_radius: nil, bottom: nil, col: nil, color: nil, content: nil, data: nil, disabled: nil, disabled_bgcolor: nil, expand: nil, expand_loose: nil, focus_color: nil, height: nil, icon: nil, icon_color: nil, key: nil, left: nil, margin: nil, min_size: nil, mouse_cursor: nil, offset: nil, opacity: nil, opacity_on_click: nil, padding: nil, right: nil, rotate: nil, rtl: nil, scale: nil, size: nil, size_change_interval: nil, tooltip: nil, top: nil, url: nil, visible: nil, width: nil, on_animation_end: nil, on_blur: nil, on_click: nil, on_focus: nil, on_long_press: nil, on_size_change: nil)
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
+
13
+ def initialize(id: nil, **props)
14
+ unknown = props.keys.reject { |key| KEYWORDS.include?(key) }
15
+ raise ArgumentError, "unknown keywords: #{unknown.join(', ')}" unless unknown.empty?
16
+ align = props[:align]
17
+ alignment = props[:alignment]
18
+ animate_align = props[:animate_align]
19
+ animate_margin = props[:animate_margin]
20
+ animate_offset = props[:animate_offset]
21
+ animate_opacity = props[:animate_opacity]
22
+ animate_position = props[:animate_position]
23
+ animate_rotation = props[:animate_rotation]
24
+ animate_scale = props[:animate_scale]
25
+ animate_size = props[:animate_size]
26
+ aspect_ratio = props[:aspect_ratio]
27
+ autofocus = props[:autofocus]
28
+ badge = props[:badge]
29
+ bgcolor = props[:bgcolor]
30
+ border_radius = props[:border_radius]
31
+ bottom = props[:bottom]
32
+ col = props[:col]
33
+ color = props[:color]
34
+ content = props[:content]
35
+ data = props[:data]
36
+ disabled = props[:disabled]
37
+ disabled_bgcolor = props[:disabled_bgcolor]
38
+ expand = props[:expand]
39
+ expand_loose = props[:expand_loose]
40
+ focus_color = props[:focus_color]
41
+ height = props[:height]
42
+ icon = props[:icon]
43
+ icon_color = props[:icon_color]
44
+ key = props[:key]
45
+ left = props[:left]
46
+ margin = props[:margin]
47
+ min_size = props[:min_size]
48
+ mouse_cursor = props[:mouse_cursor]
49
+ offset = props[:offset]
50
+ opacity = props[:opacity]
51
+ opacity_on_click = props[:opacity_on_click]
52
+ padding = props[:padding]
53
+ right = props[:right]
54
+ rotate = props[:rotate]
55
+ rtl = props[:rtl]
56
+ scale = props[:scale]
57
+ size = props[:size]
58
+ size_change_interval = props[:size_change_interval]
59
+ tooltip = props[:tooltip]
60
+ top = props[:top]
61
+ url = props[:url]
62
+ visible = props[:visible]
63
+ width = props[:width]
64
+ on_animation_end = props[:on_animation_end]
65
+ on_blur = props[:on_blur]
66
+ on_click = props[:on_click]
67
+ on_focus = props[:on_focus]
68
+ on_long_press = props[:on_long_press]
69
+ on_size_change = props[:on_size_change]
12
70
  alignment = "center" if alignment.nil?
13
71
  autofocus = false if autofocus.nil?
14
72
  border_radius = { "all" => 8.0 } if border_radius.nil?
15
73
  opacity_on_click = 0.4 if opacity_on_click.nil?
16
74
  size = "large" if size.nil?
17
- unless opacity_on_click.respond_to?(:between?) && opacity_on_click.between?(0.0, 1.0)
18
- raise ArgumentError, "cupertino_button opacity_on_click must be between 0.0 and 1.0"
19
- end
20
75
 
21
76
  props = {}
22
77
  props[:align] = align unless align.nil?
@@ -8,7 +8,62 @@ module Ruflet
8
8
  TYPE = "cupertinocheckbox".freeze
9
9
  WIRE = "CupertinoCheckbox".freeze
10
10
 
11
- def initialize(id: nil, active_color: nil, align: nil, animate_align: nil, animate_margin: nil, animate_offset: nil, animate_opacity: nil, animate_position: nil, animate_rotation: nil, animate_scale: nil, animate_size: nil, aspect_ratio: nil, autofocus: nil, badge: nil, border_side: nil, bottom: nil, check_color: nil, col: nil, data: nil, disabled: nil, expand: nil, expand_loose: nil, fill_color: nil, focus_color: nil, height: nil, key: nil, label: nil, label_position: nil, left: nil, margin: nil, mouse_cursor: nil, offset: nil, opacity: nil, right: nil, rotate: nil, rtl: nil, scale: nil, semantics_label: nil, shape: nil, size_change_interval: nil, spacing: nil, tooltip: nil, top: nil, tristate: nil, value: nil, visible: nil, width: nil, on_animation_end: nil, on_blur: nil, on_change: nil, on_focus: nil, on_size_change: nil)
11
+ KEYWORDS = [:active_color, :align, :animate_align, :animate_margin, :animate_offset, :animate_opacity, :animate_position, :animate_rotation, :animate_scale, :animate_size, :aspect_ratio, :autofocus, :badge, :border_side, :bottom, :check_color, :col, :data, :disabled, :expand, :expand_loose, :fill_color, :focus_color, :height, :key, :label, :label_position, :left, :margin, :mouse_cursor, :offset, :opacity, :right, :rotate, :rtl, :scale, :semantics_label, :shape, :size_change_interval, :spacing, :tooltip, :top, :tristate, :value, :visible, :width, :on_animation_end, :on_blur, :on_change, :on_focus, :on_size_change].freeze
12
+
13
+ def initialize(id: nil, **props)
14
+ unknown = props.keys.reject { |key| KEYWORDS.include?(key) }
15
+ raise ArgumentError, "unknown keywords: #{unknown.join(', ')}" unless unknown.empty?
16
+ active_color = props[:active_color]
17
+ align = props[:align]
18
+ animate_align = props[:animate_align]
19
+ animate_margin = props[:animate_margin]
20
+ animate_offset = props[:animate_offset]
21
+ animate_opacity = props[:animate_opacity]
22
+ animate_position = props[:animate_position]
23
+ animate_rotation = props[:animate_rotation]
24
+ animate_scale = props[:animate_scale]
25
+ animate_size = props[:animate_size]
26
+ aspect_ratio = props[:aspect_ratio]
27
+ autofocus = props[:autofocus]
28
+ badge = props[:badge]
29
+ border_side = props[:border_side]
30
+ bottom = props[:bottom]
31
+ check_color = props[:check_color]
32
+ col = props[:col]
33
+ data = props[:data]
34
+ disabled = props[:disabled]
35
+ expand = props[:expand]
36
+ expand_loose = props[:expand_loose]
37
+ fill_color = props[:fill_color]
38
+ focus_color = props[:focus_color]
39
+ height = props[:height]
40
+ key = props[:key]
41
+ label = props[:label]
42
+ label_position = props[:label_position]
43
+ left = props[:left]
44
+ margin = props[:margin]
45
+ mouse_cursor = props[:mouse_cursor]
46
+ offset = props[:offset]
47
+ opacity = props[:opacity]
48
+ right = props[:right]
49
+ rotate = props[:rotate]
50
+ rtl = props[:rtl]
51
+ scale = props[:scale]
52
+ semantics_label = props[:semantics_label]
53
+ shape = props[:shape]
54
+ size_change_interval = props[:size_change_interval]
55
+ spacing = props[:spacing]
56
+ tooltip = props[:tooltip]
57
+ top = props[:top]
58
+ tristate = props[:tristate]
59
+ value = props[:value]
60
+ visible = props[:visible]
61
+ width = props[:width]
62
+ on_animation_end = props[:on_animation_end]
63
+ on_blur = props[:on_blur]
64
+ on_change = props[:on_change]
65
+ on_focus = props[:on_focus]
66
+ on_size_change = props[:on_size_change]
12
67
  autofocus = false if autofocus.nil?
13
68
  label_position = "right" if label_position.nil?
14
69
  spacing = 10 if spacing.nil?
@@ -10,9 +10,7 @@ module Ruflet
10
10
 
11
11
  def initialize(id: nil, actions: nil, adaptive: nil, badge: nil, col: nil, content: nil, data: nil, disabled: nil, enable_haptic_feedback: nil, expand: nil, expand_loose: nil, key: nil, opacity: nil, rtl: nil, tooltip: nil, visible: nil)
12
12
  enable_haptic_feedback = true if enable_haptic_feedback.nil?
13
- visible_actions = Array(actions).reject { |action| hidden_control?(action) }
14
- raise ArgumentError, "cupertino_context_menu requires visible content" if content.nil? || hidden_control?(content)
15
- raise ArgumentError, "cupertino_context_menu requires at least one visible action" if visible_actions.empty?
13
+ raise ArgumentError, "cupertino_context_menu requires content" if content.nil?
16
14
 
17
15
  props = {}
18
16
  props[:actions] = actions unless actions.nil?
@@ -9,7 +9,7 @@ module Ruflet
9
9
  WIRE = "CupertinoContextMenuAction".freeze
10
10
 
11
11
  def initialize(id: nil, adaptive: nil, badge: nil, col: nil, content: nil, data: nil, default: nil, destructive: nil, disabled: nil, expand: nil, expand_loose: nil, key: nil, opacity: nil, rtl: nil, tooltip: nil, trailing_icon: nil, visible: nil, on_click: nil)
12
- raise ArgumentError, "cupertino_context_menu_action requires visible content" if content.nil? || (content.respond_to?(:props) && content.props["visible"] == false)
12
+ raise ArgumentError, "cupertino_context_menu_action requires content" if content.nil?
13
13
  default = false if default.nil?
14
14
  destructive = false if destructive.nil?
15
15
 
@@ -8,20 +8,65 @@ module Ruflet
8
8
  TYPE = "cupertinodatepicker".freeze
9
9
  WIRE = "CupertinoDatePicker".freeze
10
10
 
11
- def initialize(id: nil, align: nil, animate_align: nil, animate_margin: nil, animate_offset: nil, animate_opacity: nil, animate_position: nil, animate_rotation: nil, animate_scale: nil, animate_size: nil, aspect_ratio: nil, badge: nil, bgcolor: nil, bottom: nil, col: nil, data: nil, date_order: nil, date_picker_mode: nil, disabled: nil, expand: nil, expand_loose: nil, first_date: nil, height: nil, item_extent: nil, key: nil, last_date: nil, left: nil, locale: nil, margin: nil, maximum_year: nil, minimum_year: nil, minute_interval: nil, offset: nil, opacity: nil, right: nil, rotate: nil, rtl: nil, scale: nil, show_day_of_week: nil, size_change_interval: nil, tooltip: nil, top: nil, use_24h_format: nil, value: nil, visible: nil, width: nil, on_animation_end: nil, on_change: nil, on_size_change: nil)
11
+ KEYWORDS = [:align, :animate_align, :animate_margin, :animate_offset, :animate_opacity, :animate_position, :animate_rotation, :animate_scale, :animate_size, :aspect_ratio, :badge, :bgcolor, :bottom, :col, :data, :date_order, :date_picker_mode, :disabled, :expand, :expand_loose, :first_date, :height, :item_extent, :key, :last_date, :left, :locale, :margin, :maximum_year, :minimum_year, :minute_interval, :offset, :opacity, :right, :rotate, :rtl, :scale, :show_day_of_week, :size_change_interval, :tooltip, :top, :use_24h_format, :value, :visible, :width, :on_animation_end, :on_change, :on_size_change].freeze
12
+
13
+ def initialize(id: nil, **props)
14
+ unknown = props.keys.reject { |key| KEYWORDS.include?(key) }
15
+ raise ArgumentError, "unknown keywords: #{unknown.join(', ')}" unless unknown.empty?
16
+ align = props[:align]
17
+ animate_align = props[:animate_align]
18
+ animate_margin = props[:animate_margin]
19
+ animate_offset = props[:animate_offset]
20
+ animate_opacity = props[:animate_opacity]
21
+ animate_position = props[:animate_position]
22
+ animate_rotation = props[:animate_rotation]
23
+ animate_scale = props[:animate_scale]
24
+ animate_size = props[:animate_size]
25
+ aspect_ratio = props[:aspect_ratio]
26
+ badge = props[:badge]
27
+ bgcolor = props[:bgcolor]
28
+ bottom = props[:bottom]
29
+ col = props[:col]
30
+ data = props[:data]
31
+ date_order = props[:date_order]
32
+ date_picker_mode = props[:date_picker_mode]
33
+ disabled = props[:disabled]
34
+ expand = props[:expand]
35
+ expand_loose = props[:expand_loose]
36
+ first_date = props[:first_date]
37
+ height = props[:height]
38
+ item_extent = props[:item_extent]
39
+ key = props[:key]
40
+ last_date = props[:last_date]
41
+ left = props[:left]
42
+ locale = props[:locale]
43
+ margin = props[:margin]
44
+ maximum_year = props[:maximum_year]
45
+ minimum_year = props[:minimum_year]
46
+ minute_interval = props[:minute_interval]
47
+ offset = props[:offset]
48
+ opacity = props[:opacity]
49
+ right = props[:right]
50
+ rotate = props[:rotate]
51
+ rtl = props[:rtl]
52
+ scale = props[:scale]
53
+ show_day_of_week = props[:show_day_of_week]
54
+ size_change_interval = props[:size_change_interval]
55
+ tooltip = props[:tooltip]
56
+ top = props[:top]
57
+ use_24h_format = props[:use_24h_format]
58
+ value = props[:value]
59
+ visible = props[:visible]
60
+ width = props[:width]
61
+ on_animation_end = props[:on_animation_end]
62
+ on_change = props[:on_change]
63
+ on_size_change = props[:on_size_change]
12
64
  date_picker_mode = "date_and_time" if date_picker_mode.nil?
13
65
  item_extent = 32.0 if item_extent.nil?
14
66
  minimum_year = 1 if minimum_year.nil?
15
67
  minute_interval = 1 if minute_interval.nil?
16
68
  show_day_of_week = false if show_day_of_week.nil?
17
69
  use_24h_format = false if use_24h_format.nil?
18
- raise ArgumentError, "cupertino_date_picker item_extent must be greater than 0" unless item_extent.positive?
19
- unless minute_interval.positive? && (60 % minute_interval).zero?
20
- raise ArgumentError, "cupertino_date_picker minute_interval must be a positive factor of 60"
21
- end
22
- if show_day_of_week && date_picker_mode != "date"
23
- raise ArgumentError, "cupertino_date_picker show_day_of_week requires date_picker_mode: 'date'"
24
- end
25
70
 
26
71
  props = {}
27
72
  props[:align] = align unless align.nil?
@@ -9,7 +9,7 @@ module Ruflet
9
9
  WIRE = "CupertinoDialogAction".freeze
10
10
 
11
11
  def initialize(id: nil, badge: nil, col: nil, content: nil, data: nil, default: nil, destructive: nil, disabled: nil, expand: nil, expand_loose: nil, key: nil, opacity: nil, rtl: nil, text_style: nil, tooltip: nil, visible: nil, on_click: nil)
12
- raise ArgumentError, "cupertino_dialog_action requires visible content" if content.nil? || (content.respond_to?(:props) && content.props["visible"] == false)
12
+ raise ArgumentError, "cupertino_dialog_action requires content" if content.nil?
13
13
  default = false if default.nil?
14
14
  destructive = false if destructive.nil?
15
15