hyper-react 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +11 -0
  4. data/Appraisals +10 -0
  5. data/CHANGELOG.md +31 -0
  6. data/Gemfile +2 -0
  7. data/README.md +7 -0
  8. data/gemfiles/opal_0.10_react_13.gemfile +4 -0
  9. data/gemfiles/opal_0.10_react_14.gemfile +4 -0
  10. data/gemfiles/opal_0.10_react_15.gemfile +4 -0
  11. data/gemfiles/opal_0.8_react_13.gemfile +4 -0
  12. data/gemfiles/opal_0.8_react_14.gemfile +4 -0
  13. data/gemfiles/opal_0.8_react_15.gemfile +4 -0
  14. data/gemfiles/opal_0.9_react_13.gemfile +4 -0
  15. data/gemfiles/opal_0.9_react_14.gemfile +4 -0
  16. data/gemfiles/opal_0.9_react_15.gemfile +4 -0
  17. data/gemfiles/opal_master_react_15.gemfile +18 -0
  18. data/hyper-react.gemspec +4 -0
  19. data/lib/hyper-react.rb +24 -4
  20. data/lib/rails-helpers/top_level_rails_component.rb +1 -1
  21. data/lib/react/api.rb +10 -0
  22. data/lib/react/component.rb +135 -106
  23. data/lib/react/component/base.rb +5 -1
  24. data/lib/react/component/class_methods.rb +12 -37
  25. data/lib/react/component/dsl_instance_methods.rb +0 -4
  26. data/lib/react/component/props_wrapper.rb +0 -5
  27. data/lib/react/component/should_component_update.rb +1 -5
  28. data/lib/react/component/tags.rb +7 -22
  29. data/lib/react/config.rb +5 -0
  30. data/lib/react/config/client.rb.erb +19 -0
  31. data/lib/react/config/server.rb +20 -0
  32. data/lib/react/element.rb +1 -0
  33. data/lib/react/native_library.rb +2 -7
  34. data/lib/react/react-source-browser.rb +3 -0
  35. data/lib/react/react-source-server.rb +3 -0
  36. data/lib/react/react-source.rb +12 -1
  37. data/lib/react/ref_callback.rb +31 -0
  38. data/lib/react/rendering_context.rb +9 -9
  39. data/lib/react/server.rb +23 -0
  40. data/lib/react/state_wrapper.rb +23 -0
  41. data/lib/react/test/matchers/render_html_matcher.rb +4 -2
  42. data/lib/react/top_level.rb +2 -0
  43. data/lib/reactive-ruby/component_loader.rb +2 -1
  44. data/lib/reactive-ruby/isomorphic_helpers.rb +10 -0
  45. data/lib/reactive-ruby/version.rb +1 -1
  46. data/lib/reactrb/auto-import.rb +2 -7
  47. data/spec/react/callbacks_spec.rb +8 -7
  48. data/spec/react/component_spec.rb +24 -13
  49. data/spec/react/dsl_spec.rb +12 -8
  50. data/spec/react/element_spec.rb +7 -7
  51. data/spec/react/native_library_spec.rb +25 -43
  52. data/spec/react/param_declaration_spec.rb +9 -0
  53. data/spec/react/react_spec.rb +0 -7
  54. data/spec/react/refs_callback_spec.rb +56 -0
  55. data/spec/react/server_spec.rb +25 -0
  56. data/spec/react/state_spec.rb +3 -3
  57. data/spec/react/top_level_component_spec.rb +1 -1
  58. data/spec/spec_helper.rb +31 -1
  59. metadata +72 -9
  60. data/lib/react/observable.rb +0 -29
  61. data/lib/react/state.rb +0 -191
  62. data/lib/sources/react-latest.js +0 -21169
  63. data/lib/sources/react-v13.js +0 -21645
  64. data/lib/sources/react-v14.js +0 -20821
  65. data/lib/sources/react-v15.js +0 -21170
@@ -2,7 +2,11 @@ module React
2
2
  module Component
3
3
  class Base
4
4
  def self.inherited(child)
5
- child.include(Component)
5
+ # note this is turned off during old style testing: See the spec_helper
6
+ unless child.to_s == "React::Component::HyperTestDummy"
7
+ React::Component.deprecation_warning child, "The class name React::Component::Base has been deprecated. Use Hyperloop::Component instead."
8
+ end
9
+ child.include(ComponentNoNotice)
6
10
  end
7
11
  end
8
12
  end
@@ -3,6 +3,10 @@ module React
3
3
  # class level methods (macros) for components
4
4
  module ClassMethods
5
5
 
6
+ def deprecation_warning(message)
7
+ React::Component.deprecation_warning(self, message)
8
+ end
9
+
6
10
  def reactrb_component?
7
11
  true
8
12
  end
@@ -113,51 +117,22 @@ module React
113
117
  end
114
118
 
115
119
  def define_state(*states, &block)
120
+ deprecation_warning "'define_state' is deprecated. Use the 'state' macro to declare states."
116
121
  default_initial_value = (block && block.arity == 0) ? yield : nil
117
122
  states_hash = (states.last.is_a?(Hash)) ? states.pop : {}
118
- states.each { |name| states_hash[name] = default_initial_value }
119
- (self.initial_state ||= {}).merge! states_hash
120
- states_hash.each do |name, initial_value|
121
- define_state_methods(self, name, &block)
122
- end
123
+ states.each { |name| state(name => default_initial_value) } # was states_hash[name] = default_initial_value
124
+ states_hash.each { |name, value| state(name => value) }
123
125
  end
124
126
 
125
127
  def export_state(*states, &block)
128
+ deprecation_warning "'export_state' is deprecated. Use the 'state' macro to declare states."
126
129
  default_initial_value = (block && block.arity == 0) ? yield : nil
127
130
  states_hash = (states.last.is_a?(Hash)) ? states.pop : {}
128
131
  states.each { |name| states_hash[name] = default_initial_value }
129
- State.initialize_states(self, states_hash)
130
- states_hash.each do |name, initial_value|
131
- define_state_methods(self, name, self, &block)
132
- define_state_methods(singleton_class, name, self, &block)
133
- end
134
- end
135
-
136
- def define_state_methods(this, name, from = nil, &block)
137
- this.define_method("#{name}") do
138
- React::Component.deprecation_warning "Direct access to state `#{name}`. Use `state.#{name}` instead." if from.nil? || from == this
139
- State.get_state(from || self, name)
140
- end
141
- this.define_method("#{name}=") do |new_state|
142
- React::Component.deprecation_warning "Direct assignment to state `#{name}`. Use `#{(from && from != this) ? from : 'state'}.#{name}!` instead."
143
- yield name, State.get_state(from || self, name), new_state if block && block.arity > 0
144
- State.set_state(from || self, name, new_state)
145
- end
146
- this.define_method("#{name}!") do |*args|
147
- React::Component.deprecation_warning "Direct access to state `#{name}`. Use `state.#{name}` instead." if from.nil? or from == this
148
- if args.count > 0
149
- yield name, State.get_state(from || self, name), args[0] if block && block.arity > 0
150
- current_value = State.get_state(from || self, name)
151
- State.set_state(from || self, name, args[0])
152
- current_value
153
- else
154
- current_state = State.get_state(from || self, name)
155
- yield name, State.get_state(from || self, name), current_state if block && block.arity > 0
156
- State.set_state(from || self, name, current_state)
157
- Observable.new(current_state) do |update|
158
- yield name, State.get_state(from || self, name), update if block && block.arity > 0
159
- State.set_state(from || self, name, update)
160
- end
132
+ states_hash.each do |name, value|
133
+ state(name => value, scope: :class, reader: true)
134
+ singleton_class.define_method("#{name}!") do |*args|
135
+ mutate.__send__(name, *args)
161
136
  end
162
137
  end
163
138
  end
@@ -18,10 +18,6 @@ module React
18
18
  def refs
19
19
  Hash.new(`#{@native}.refs`)
20
20
  end
21
-
22
- def state
23
- @state_wrapper ||= StateWrapper.new(@native, self)
24
- end
25
21
  end
26
22
  end
27
23
  end
@@ -1,11 +1,6 @@
1
1
  module React
2
2
  module Component
3
3
 
4
- def deprecated_params_method(name, *args, &block)
5
- React::Component.deprecation_warning"Direct access to param `#{name}`. Use `params.#{name}` instead."
6
- params.send(name, *args, &block)
7
- end
8
-
9
4
  class PropsWrapper
10
5
  attr_reader :component
11
6
 
@@ -83,13 +83,9 @@ module React
83
83
  end
84
84
  # rubocop:enable Metrics/MethodLength
85
85
 
86
- # Do a shallow compare on the two hashes. Starting in 0.9 we will do a deep compare.
86
+ # Do a shallow compare on the two hashes. Starting in 0.9 we will do a deep compare. ???
87
87
 
88
88
  def props_changed?(next_params)
89
- Component.deprecation_warning(
90
- "Using shallow incoming params comparison.\n"\
91
- 'Do a require "reactrb/deep-compare, to get 0.9 behavior'
92
- )
93
89
  (props.keys.sort != next_params.keys.sort) ||
94
90
  next_params.detect { |k, v| `#{v} != #{@native}.props[#{k}]` }
95
91
  end
@@ -27,18 +27,12 @@ module React
27
27
  %w(circle clipPath defs ellipse g line linearGradient mask path pattern polygon polyline
28
28
  radialGradient rect stop svg text tspan)
29
29
 
30
- # note: any tag can end in _as_node but this is deprecated
31
-
32
30
  # the present method is retained as a legacy behavior
33
31
 
34
32
  def present(component, *params, &children)
35
33
  React::RenderingContext.render(component, *params, &children)
36
34
  end
37
35
 
38
- def present_as_node(component, *params, &children)
39
- React::RenderingContext.build_only(component, *params, &children)
40
- end
41
-
42
36
  # define each predefined tag as an instance method
43
37
 
44
38
 
@@ -64,10 +58,6 @@ module React
64
58
  #const_set tag.upcase, React.create_element(tag)
65
59
  #Object.const_set tag.upcase, Class.new(HtmlTagWrapper)
66
60
  end
67
- # handle deprecated _as_node style
68
- define_method("#{tag}_as_node") do |*params, &children|
69
- React::RenderingContext.build_only(tag, *params, &children)
70
- end
71
61
  end
72
62
 
73
63
  def self.html_tag_class_for(tag)
@@ -81,14 +71,8 @@ module React
81
71
  # where there is no preceeding scope.
82
72
 
83
73
  def method_missing(name, *params, &children)
84
- if name =~ /_as_node$/
85
- # handle deprecated _as_node style
86
- component = find_component(name.gsub(/_as_node$/, ''))
87
- return React::RenderingContext.build_only(component, *params, &children) if component
88
- else
89
- component = find_component(name)
90
- return React::RenderingContext.render(component, *params, &children) if component
91
- end
74
+ component = find_component(name)
75
+ return React::RenderingContext.render(component, *params, &children) if component
92
76
  Object.method_missing(name, *params, &children)
93
77
  end
94
78
 
@@ -97,16 +81,17 @@ module React
97
81
 
98
82
  class << self
99
83
  def included(component)
100
- _name, parent = find_name_and_parent(component)
101
- class << parent
102
- define_method _name do |*params, &children|
84
+ name, parent = find_name_and_parent(component)
85
+ tag_names_module = Module.new do
86
+ define_method name do |*params, &children|
103
87
  React::RenderingContext.render(component, *params, &children)
104
88
  end
105
89
  # handle deprecated _as_node style
106
- define_method "#{_name}_as_node" do |*params, &children|
90
+ define_method "#{name}_as_node" do |*params, &children|
107
91
  React::RenderingContext.build_only(component, *params, &children)
108
92
  end
109
93
  end
94
+ parent.extend(tag_names_module)
110
95
  end
111
96
 
112
97
  private
@@ -0,0 +1,5 @@
1
+ if RUBY_ENGINE != 'opal'
2
+ require "react/config/server"
3
+ else
4
+ require "react/config/client"
5
+ end
@@ -0,0 +1,19 @@
1
+ if RUBY_ENGINE == 'opal'
2
+ module React
3
+ module Config
4
+ extend self
5
+ def environment=(value)
6
+ raise "Environment cannot be configured at runtime."
7
+ end
8
+
9
+ def config
10
+ hash = %x{
11
+ Opal.hash({
12
+ environment: <%= '"' + React::Config.config[:environment] + '"' %>
13
+ })
14
+ }
15
+ hash
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ if RUBY_ENGINE != 'opal'
2
+ module React
3
+ module Config
4
+ extend self
5
+ def environment=(value)
6
+ config[:environment] = value
7
+ end
8
+
9
+ def config
10
+ @config ||= default_config
11
+ end
12
+
13
+ def default_config
14
+ {
15
+ environment: ENV['RACK_ENV'] || 'development'
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -156,6 +156,7 @@ module React
156
156
  prop_name = "_on#{event_name.event_camelize}"
157
157
  fn = %x{function(){#{
158
158
  React::Component.deprecation_warning(
159
+ type,
159
160
  "In future releases React::Element#on('#{event_name}') will no longer respond "\
160
161
  "to the '#{prop_name}' emitter.\n"\
161
162
  "Rename your emitter param to 'on_#{event_name}' or use .on('<#{prop_name}>')"
@@ -45,17 +45,12 @@ module React
45
45
  import_const_from_native(self, const_name, true) || super
46
46
  end
47
47
 
48
- def method_missing(method_name, *args, &block)
49
- method = method_name.gsub(/_as_node$/, '') # remove once _as_node is deprecated.
48
+ def method_missing(method, *args, &block)
50
49
  component_class = get_const(method) if const_defined?(method)
51
50
  component_class ||= import_const_from_native(self, method, false)
52
51
  raise 'could not import a react component named: '\
53
52
  "#{scope_native_name method}" unless component_class
54
- if method == method_name
55
- React::RenderingContext.render(component_class, *args, &block)
56
- else # remove once _as_node is deprecated.
57
- React::RenderingContext.build_only(component_class, *args, &block)
58
- end
53
+ React::RenderingContext.render(component_class, *args, &block)
59
54
  end
60
55
 
61
56
  private
@@ -0,0 +1,3 @@
1
+ if RUBY_ENGINE == 'opal'
2
+ require 'react.js'
3
+ end
@@ -0,0 +1,3 @@
1
+ if RUBY_ENGINE == 'opal'
2
+ require "react-server.js"
3
+ end
@@ -1,9 +1,20 @@
1
1
  if RUBY_ENGINE == 'opal'
2
+ %x{
3
+ var ms = [
4
+ "Warning: `react/react-source` is deprecated, ",
5
+ "use `react/react-source-browser` or `react/react-source-server` instead."
6
+ ]
7
+ console.error(ms.join(""));
8
+ }
2
9
  require 'react.js'
3
10
  require "react-server.js"
4
11
  else
12
+ require "react/config"
5
13
  require "react/rails/asset_variant"
6
- react_directory = React::Rails::AssetVariant.new(addons: true).react_directory
14
+ react_directory = React::Rails::AssetVariant.new(
15
+ addons: true,
16
+ variant: React::Config.config[:environment].to_sym
17
+ ).react_directory
7
18
  Opal.append_path react_directory.untaint
8
19
  Opal.append_path File.expand_path('../../react-sources/', __FILE__).untaint
9
20
  end
@@ -0,0 +1,31 @@
1
+ require 'react/native_library'
2
+
3
+ module React
4
+ module RefsCallbackExtension
5
+ end
6
+
7
+ class API
8
+ class << self
9
+ alias :orig_convert_props :convert_props
10
+ end
11
+
12
+ def self.convert_props(properties)
13
+ props = self.orig_convert_props(properties)
14
+ props.map do |key, value|
15
+ if key == "ref" && value.is_a?(Proc)
16
+ new_proc = Proc.new do |native_inst|
17
+ if `#{native_inst}._getOpalInstance !== undefined`
18
+ value.call(`#{native_inst}._getOpalInstance()`)
19
+ elsif `React.findDOMNode !== undefined && #{native_inst}.nodeType === undefined`
20
+ value.call(`React.findDOMNode(#{native_inst})`)
21
+ else
22
+ value.call(native_inst)
23
+ end
24
+ end
25
+ props[key] = new_proc
26
+ end
27
+ end
28
+ props
29
+ end
30
+ end
31
+ end
@@ -3,14 +3,9 @@ module React
3
3
  class << self
4
4
  attr_accessor :waiting_on_resources
5
5
 
6
- def build_only(name, *args, &block)
7
- React::Component.deprecation_warning(
8
- '..._as_node is deprecated. Render component and then use the .node method instead'
9
- )
10
- React::RenderingContext.build { React::RenderingContext.render(name, *args, &block) }.to_n
11
- end
12
-
13
6
  def render(name, *args, &block)
7
+ was_outer_most = !@not_outer_most
8
+ @not_outer_most = true
14
9
  remove_nodes_from_args(args)
15
10
  @buffer ||= [] unless @buffer
16
11
  if block
@@ -38,6 +33,8 @@ module React
38
33
  @buffer << element
39
34
  self.waiting_on_resources = nil
40
35
  element
36
+ ensure
37
+ @not_outer_most = @buffer = nil if was_outer_most
41
38
  end
42
39
 
43
40
  def build
@@ -65,7 +62,10 @@ module React
65
62
 
66
63
  def remove_nodes_from_args(args)
67
64
  args[0].each do |key, value|
68
- value.as_node if value.is_a?(Element) rescue nil
65
+ begin
66
+ value.as_node if value.is_a?(Element)
67
+ rescue Exception
68
+ end
69
69
  end if args[0] && args[0].is_a?(Hash)
70
70
  end
71
71
 
@@ -92,7 +92,7 @@ module React
92
92
  def run_child_block(is_outer_scope)
93
93
  result = yield
94
94
  result = result.to_s if result.try :acts_as_string?
95
- @buffer << result if result.is_a?(String) || (result.is_a?(Element) && @buffer.empty?)
95
+ @buffer << result if result.is_a?(String) || (result.is_a?(React::Element) && @buffer.empty?)
96
96
  raise_render_error(result) if is_outer_scope && @buffer != [result]
97
97
  end
98
98
 
@@ -0,0 +1,23 @@
1
+ module React
2
+ module Server
3
+ def self.render_to_string(element)
4
+ if !(`typeof ReactDOMServer === 'undefined'`)
5
+ React::RenderingContext.build { `ReactDOMServer.renderToString(#{element.to_n})` } # v0.15+
6
+ elsif !(`typeof React.renderToString === 'undefined'`)
7
+ React::RenderingContext.build { `React.renderToString(#{element.to_n})` }
8
+ else
9
+ raise "renderToString is not defined. In React >= v15 you must import it with ReactDOMServer"
10
+ end
11
+ end
12
+
13
+ def self.render_to_static_markup(element)
14
+ if !(`typeof ReactDOMServer === 'undefined'`)
15
+ React::RenderingContext.build { `ReactDOMServer.renderToStaticMarkup(#{element.to_n})` } # v0.15+
16
+ elsif !(`typeof React.renderToString === 'undefined'`)
17
+ React::RenderingContext.build { `React.renderToStaticMarkup(#{element.to_n})` }
18
+ else
19
+ raise "renderToStaticMarkup is not defined. In React >= v15 you must import it with ReactDOMServer"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module HyperStore
2
+ class StateWrapper < BaseStoreClass # < BasicObject
3
+
4
+ def [](state)
5
+ `#{__from__.instance_variable_get('@native')}.state[#{state}] || #{nil}`
6
+ end
7
+
8
+ def []=(state, new_value)
9
+ `#{__from__.instance_variable_get('@native')}.state[#{state}] = new_value`
10
+ end
11
+
12
+ alias pre_component_method_missing method_missing
13
+
14
+ def method_missing(method, *args)
15
+ if method =~ /\!$/ && __from__.respond_to?(:deprecation_warning)
16
+ __from__.deprecation_warning("The mutator 'state.#{method}' has been deprecated. Use 'mutate.#{method.gsub(/\!$/,'')}' instead.")
17
+ __from__.mutate.__send__(method.gsub(/\!$/,''), *args)
18
+ else
19
+ pre_component_method_missing(method, *args)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -22,15 +22,17 @@ module React
22
22
  failure_string
23
23
  end
24
24
 
25
- def negative_failure_message
25
+ def failure_message_when_negated
26
26
  failure_string(:negative)
27
27
  end
28
28
 
29
+ alias negative_failure_message failure_message_when_negated
30
+
29
31
  private
30
32
 
31
33
  def render_to_html
32
34
  element = React.create_element(@component, @params)
33
- React.render_to_static_markup(element)
35
+ React::Server.render_to_static_markup(element)
34
36
  end
35
37
 
36
38
  def failure_string(negative = false)