isomorfeus-react 16.5.1

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 (63) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +1 -0
  3. data/README.md +620 -0
  4. data/isomorfeus-react.gemspec +23 -0
  5. data/lib/isomorfeus-react.rb +131 -0
  6. data/lib/isomorfeus/config.rb +84 -0
  7. data/lib/isomorfeus/top_level.rb +48 -0
  8. data/lib/isomorfeus/view_helpers.rb +38 -0
  9. data/lib/lucid_app/api.rb +22 -0
  10. data/lib/lucid_app/base.rb +7 -0
  11. data/lib/lucid_app/context.rb +7 -0
  12. data/lib/lucid_app/mixin.rb +17 -0
  13. data/lib/lucid_app/native_component_constructor.rb +70 -0
  14. data/lib/lucid_component/api.rb +97 -0
  15. data/lib/lucid_component/base.rb +7 -0
  16. data/lib/lucid_component/event_handler.rb +17 -0
  17. data/lib/lucid_component/initializer.rb +12 -0
  18. data/lib/lucid_component/mixin.rb +17 -0
  19. data/lib/lucid_component/native_component_constructor.rb +131 -0
  20. data/lib/react.rb +147 -0
  21. data/lib/react/active_support_support.rb +13 -0
  22. data/lib/react/component/api.rb +226 -0
  23. data/lib/react/component/base.rb +9 -0
  24. data/lib/react/component/elements.rb +78 -0
  25. data/lib/react/component/event_handler.rb +19 -0
  26. data/lib/react/component/features.rb +47 -0
  27. data/lib/react/component/history.rb +36 -0
  28. data/lib/react/component/initializer.rb +11 -0
  29. data/lib/react/component/location.rb +15 -0
  30. data/lib/react/component/match.rb +31 -0
  31. data/lib/react/component/mixin.rb +19 -0
  32. data/lib/react/component/native_component_constructor.rb +76 -0
  33. data/lib/react/component/native_component_validate_prop.rb +37 -0
  34. data/lib/react/component/props.rb +49 -0
  35. data/lib/react/component/resolution.rb +71 -0
  36. data/lib/react/component/should_component_update.rb +14 -0
  37. data/lib/react/component/state.rb +52 -0
  38. data/lib/react/component/unsafe_api.rb +33 -0
  39. data/lib/react/context_wrapper.rb +47 -0
  40. data/lib/react/function_component/creator.rb +47 -0
  41. data/lib/react/function_component/resolution.rb +61 -0
  42. data/lib/react/function_component/runner.rb +19 -0
  43. data/lib/react/native_constant_wrapper.rb +34 -0
  44. data/lib/react/pure_component/base.rb +9 -0
  45. data/lib/react/pure_component/mixin.rb +17 -0
  46. data/lib/react/redux_component/api.rb +132 -0
  47. data/lib/react/redux_component/app_store_defaults.rb +38 -0
  48. data/lib/react/redux_component/app_store_proxy.rb +46 -0
  49. data/lib/react/redux_component/base.rb +9 -0
  50. data/lib/react/redux_component/class_store_proxy.rb +50 -0
  51. data/lib/react/redux_component/component_class_store_defaults.rb +40 -0
  52. data/lib/react/redux_component/component_instance_store_defaults.rb +41 -0
  53. data/lib/react/redux_component/initializer.rb +14 -0
  54. data/lib/react/redux_component/instance_store_proxy.rb +50 -0
  55. data/lib/react/redux_component/mixin.rb +18 -0
  56. data/lib/react/redux_component/native_component_constructor.rb +119 -0
  57. data/lib/react/redux_component/reducers.rb +53 -0
  58. data/lib/react/ref.rb +19 -0
  59. data/lib/react/synthetic_event.rb +53 -0
  60. data/lib/react/version.rb +3 -0
  61. data/lib/react_dom.rb +31 -0
  62. data/lib/react_dom_server.rb +17 -0
  63. metadata +167 -0
@@ -0,0 +1,61 @@
1
+ module React
2
+ module FunctionComponent
3
+ module Resolution
4
+ def self.included(base)
5
+ base.instance_exec do
6
+ alias _react_component_resolution_original_const_missing const_missing
7
+
8
+ def const_missing(const_name)
9
+ %x{
10
+ if (typeof Opal.global[const_name] == "object") {
11
+ var new_const = #{React::NativeConstantWrapper.new(`Opal.global[const_name]`, const_name)};
12
+ #{Object.const_set(const_name, `new_const`)};
13
+ return new_const;
14
+ } else {
15
+ return #{_react_component_resolution_original_const_missing(const_name)};
16
+ }
17
+ }
18
+ end
19
+ end
20
+ end
21
+
22
+ alias _react_component_resolution_original_method_missing method_missing
23
+
24
+ def method_missing(component_name, *args, &block)
25
+ # html tags are defined as methods, so they will not end up here.
26
+ # first check for native component and render it, we want to be fast for native components
27
+ # second check for ruby component and render it, they are a bit slower anyway
28
+ # third pass on method missing
29
+
30
+ %x{
31
+ var component = null;
32
+ if (typeof Opal.global[component_name] == "function") {
33
+ component = Opal.global[component_name];
34
+ }
35
+ else {
36
+ try {
37
+ var constant = self.$class().$const_get(component_name, true);
38
+ if (typeof constant.react_component == "function") {
39
+ component = constant.react_component;
40
+ }
41
+ }
42
+ catch(err) {
43
+ component = null;
44
+ }
45
+ }
46
+ if (component) {
47
+ var props = null;
48
+
49
+ if (args.length > 0) {
50
+ props = Opal.React.to_native_react_props(args[0]);
51
+ }
52
+ Opal.React.internal_render(component, props, block);
53
+ } else {
54
+ return #{_react_component_resolution_original_method_missing(component_name, *args, block)};
55
+ }
56
+ }
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,19 @@
1
+ module React
2
+ module FunctionComponent
3
+ class Runner
4
+ include ::React::Component::Elements
5
+ include ::React::Component::Features
6
+ include ::React::FunctionComponent::Resolution
7
+
8
+ attr_accessor :props
9
+
10
+ %x{
11
+ self.event_handlers = {};
12
+ }
13
+
14
+ def initialize(props)
15
+ @props = ::React::Component::Props.new(props)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module React
2
+ class NativeConstantWrapper
3
+ include ::Native::Wrapper
4
+
5
+ def initialize(native, const_name)
6
+ @native = native
7
+ @const_name = const_name
8
+ end
9
+
10
+ def method_missing(name, *args, &block)
11
+ %x{
12
+ var component = null;
13
+ if (typeof #@native[name] == "function") {
14
+ component = #@native[name];
15
+ }
16
+
17
+ if (component) {
18
+ var children = null;
19
+ var block_result = null;
20
+ var props = null;
21
+ var react_element;
22
+
23
+ if (args.length > 0) {
24
+ props = Opal.React.to_native_react_props(args[0]);
25
+ }
26
+ Opal.React.internal_render(component, props, block);
27
+ } else {
28
+ #{raise NameError, "No such native Component #@const_name.#{name}"};
29
+ }
30
+ }
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ module React
2
+ module PureComponent
3
+ class Base
4
+ def self.inherited(base)
5
+ base.include(::React::PureComponent::Mixin)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module React
2
+ module PureComponent
3
+ module Mixin
4
+ def self.included(base)
5
+ base.include(::Native::Wrapper)
6
+ base.extend(::React::Component::NativeComponentConstructor)
7
+ base.extend(::React::Component::NativeComponentValidateProp)
8
+ base.extend(::React::Component::EventHandler)
9
+ base.include(::React::Component::Elements)
10
+ base.include(::React::Component::API)
11
+ base.include(::React::Component::Initializer)
12
+ base.include(::React::Component::Features)
13
+ base.include(::React::Component::Resolution)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,132 @@
1
+ module React
2
+ module ReduxComponent
3
+ module API
4
+ def self.included(base)
5
+ base.instance_exec do
6
+ attr_accessor :app_store
7
+ attr_accessor :class_store
8
+ attr_accessor :store
9
+
10
+ def default_app_store_defined
11
+ @default_app_store_defined
12
+ end
13
+
14
+ def default_class_store_defined
15
+ @default_class_store_defined
16
+ end
17
+
18
+ def default_instance_store_defined
19
+ @default_instance_store_defined
20
+ end
21
+
22
+ def app_store
23
+ @default_app_store_defined = true
24
+ @default_app_store ||= ::React::ReduxComponent::AppStoreDefaults.new(state)
25
+ end
26
+
27
+ def class_store
28
+ @default_class_store_defined = true
29
+ @default_class_store ||= ::React::ReduxComponent::ComponentClassStoreDefaults.new(state, self.to_s)
30
+ end
31
+
32
+ def store
33
+ @default_instance_store_defined = true
34
+ @default_class_store ||= ::React::ReduxComponent::ComponentInstanceStoreDefaults.new(state, self.to_s)
35
+ end
36
+
37
+ def component_did_catch(&block)
38
+ # TODO convert error and info
39
+ %x{
40
+ var fun = function(error, info) {
41
+ Opal.React.active_redux_components.push(this.__ruby_instance);
42
+ #{`this.__ruby_instance`.instance_exec(error, info, &block)};
43
+ Opal.React.active_redux_components.pop();
44
+ }
45
+ if (self.lucid_react_component) { self.lucid_react_component.prototype.componentDidCatch = fun; }
46
+ else { self.react_component.prototype.componentDidCatch = fun; }
47
+ }
48
+ end
49
+
50
+ def component_did_mount(&block)
51
+ %x{
52
+ var fun = function() {
53
+ Opal.React.active_redux_components.push(this.__ruby_instance);
54
+ #{`this.__ruby_instance`.instance_exec(&block)};
55
+ Opal.React.active_redux_components.pop();
56
+ }
57
+ if (self.lucid_react_component) { self.lucid_react_component.prototype.componentDidMount = fun; }
58
+ else { self.react_component.prototype.componentDidMount = fun; }
59
+ }
60
+ end
61
+
62
+ def component_did_update(&block)
63
+ %x{
64
+ var fun = function() {
65
+ Opal.React.active_redux_components.push(this.__ruby_instance);
66
+ #{`this.__ruby_instance`.instance_exec(&block)};
67
+ Opal.React.active_redux_components.pop();
68
+ }
69
+ if (self.lucid_react_component) { self.lucid_react_component.prototype.componentDidUpdate = fun; }
70
+ else { self.react_component.prototype.componentDidUpdate = fun; }
71
+ }
72
+ end
73
+
74
+ def component_will_unmount(&block)
75
+ # unsubscriber support for ReduxComponent
76
+ %x{
77
+ var fun = function() {
78
+ if (typeof this.unsubscriber === "function") { this.unsubscriber(); };
79
+ Opal.React.active_redux_components.push(this.__ruby_instance);
80
+ #{`this.__ruby_instance`.instance_exec(&block)};
81
+ Opal.React.active_redux_components.pop();
82
+ }
83
+ if (self.lucid_react_component) { self.lucid_react_component.prototype.componentWillUnmount = fun; }
84
+ else { self.react_component.prototype.componentWillUnmount = fun; }
85
+ }
86
+ end
87
+
88
+ def get_derived_state_from_props(&block)
89
+ %x{
90
+ var fun = function(props, state) {
91
+ Opal.React.active_redux_components.push(this.__ruby_instance);
92
+ #{`this.__ruby_instance`.instance_exec(React::Component::Props.new(`props`), `Opal.Hash.$new(state)`, &block)};
93
+ Opal.React.active_redux_components.pop();
94
+ }
95
+ if (self.lucid_react_component) { self.lucid_react_component.prototype.getDerivedStateFromProps = fun; }
96
+ else { self.react_component.prototype.getDerivedStateFromProps = fun; }
97
+ }
98
+ end
99
+
100
+ def get_snapshot_before_update(&block)
101
+ %x{
102
+ var fun = function(prev_props, prev_state) {
103
+ Opal.React.active_redux_components.push(this.__ruby_instance);
104
+ #{`this.__ruby_instance`.instance_exec(React::Component::Props.new(`prev_props`), `Opal.Hash.$new(prev_state)`, &block)};
105
+ Opal.React.active_redux_components.pop();
106
+ }
107
+ if (self.lucid_react_component) { self.lucid_react_component.prototype.getSnapshotBeforeUpdate = fun; }
108
+ else { self.react_component.prototype.getSnapshotBeforeUpdate = fun; }
109
+ }
110
+ end
111
+
112
+ def render(&block)
113
+ %x{
114
+ var fun = function() {
115
+ Opal.React.render_buffer.push([]);
116
+ Opal.React.active_components.push(this);
117
+ Opal.React.active_redux_components.push(this);
118
+ this.used_store_paths = [];
119
+ #{`this.__ruby_instance`.instance_exec(&block)};
120
+ Opal.React.active_redux_components.pop();
121
+ Opal.React.active_components.pop();
122
+ return Opal.React.render_buffer.pop();
123
+ }
124
+ if (self.lucid_react_component) { self.lucid_react_component.prototype.render = fun; }
125
+ else { self.react_component.prototype.render = fun; }
126
+ }
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,38 @@
1
+ module React
2
+ module ReduxComponent
3
+ class AppStoreDefaults
4
+ def initialize(state, component_name)
5
+ @state = state
6
+ if @state.isomorfeus_store
7
+ @state.isomorfeus_store.merge!(application_state: {})
8
+ else
9
+ @state.isomorfeus_store = { application_state: {}}
10
+ end
11
+ end
12
+
13
+ def method_missing(key, *args, &block)
14
+ if `args.length > 0`
15
+ # set initial class state
16
+ key = key.chop if `key.endsWith('=')`
17
+ @state.isomorfeus_store[:application_state][key] = args[0]
18
+ current_state = Isomorfeus.store.get_state
19
+ if !(current_state[:application_state].has_key?(key))
20
+ Isomorfeus.store.dispatch(type: 'APPLICATION_STATE', name: key, value: args[0])
21
+ end
22
+ else
23
+ # get class state
24
+
25
+ # check if we have a component local state value
26
+ if @state.isomorfeus_store[:application_state].has_key?(key)
27
+ return @state.isomorfeus_store[:application_state][key]
28
+ end
29
+ end
30
+ nil
31
+ end
32
+
33
+ def to_h
34
+ @state.isomorfeus_store[:application_state]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,46 @@
1
+ module React
2
+ module ReduxComponent
3
+ class AppStoreProxy
4
+
5
+ def initialize(component_instance, access_key = 'state')
6
+ @native_component_instance = component_instance.to_n
7
+ @component_instance = component_instance
8
+ @access_key = access_key
9
+ end
10
+
11
+ def method_missing(key, *args, &block)
12
+ @native_component_instance.JS.register_used_store_path(['application_state', key])
13
+
14
+ if `args.length > 0`
15
+ # set class state, simply a dispatch
16
+
17
+ action = { type: 'APPLICATION_STATE', name: (`key.endsWith('=')` ? key.chop : key), value: args[0] }
18
+ Isomorfeus.store.dispatch(action)
19
+
20
+ else
21
+ # check if we have a component local state value
22
+ if `this.native_component_instance[this.access_key]["isomorfeus_store"]["application_state"].hasOwnProperty(key)`
23
+ return @native_component_instance.JS[@access_key].JS[:isomorfeus_store].JS[:application_state].JS[key]
24
+ elsif @component_instance.class.default_app_store_defined && @component_instance.class.app_store.to_h.has_key?(key)
25
+ # check if a default value was given
26
+ return @component_instance.class.app_store.to_h[key]
27
+ end
28
+ # otherwise return nil
29
+ return nil
30
+ end
31
+ end
32
+
33
+ def dispatch(action)
34
+ Isomorfeus.store.dispatch(action)
35
+ end
36
+
37
+ def subscribe(&block)
38
+ Isomorfeus.store.subscribe(&block)
39
+ end
40
+
41
+ def unsubscribe(unsubscriber)
42
+ `unsubscriber()`
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,9 @@
1
+ module React
2
+ module ReduxComponent
3
+ class Base
4
+ def self.inherited(base)
5
+ base.include(::React::ReduxComponent::Mixin)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ module React
2
+ module ReduxComponent
3
+ class ClassStoreProxy
4
+
5
+ def initialize(component_instance, access_key = 'state')
6
+ @native_component_instance = component_instance.to_n
7
+ @component_instance = component_instance
8
+ @component_name = component_instance.class.to_s
9
+ @access_key = access_key
10
+ end
11
+
12
+ def method_missing(key, *args, &block)
13
+ @native_component_instance.JS.register_used_store_path(['component_class_state', @component_name, key])
14
+ if `args.length > 0`
15
+ # set class state, simply a dispatch
16
+
17
+ action = { type: 'COMPONENT_CLASS_STATE', class: @component_name, name: (`key.endsWith('=')` ? key.chop : key), value: args[0] }
18
+ Isomorfeus.store.dispatch(action)
19
+
20
+ else
21
+ # get class state
22
+
23
+ # check if we have a component local state value
24
+ if @native_component_instance.JS[@access_key].JS[:isomorfeus_store].JS[:component_class_state].JS[@component_name] &&
25
+ @native_component_instance.JS[@access_key].JS[:isomorfeus_store].JS[:component_class_state].JS[@component_name].JS.hasOwnProperty(key)
26
+ return @native_component_instance.JS[@access_key].JS[:isomorfeus_store].JS[:component_class_state].JS[@component_name].JS[key]
27
+ elsif @component_instance.class.default_class_store_defined && @component_instance.class.class_store.to_h.has_key?(key)
28
+ # check if a default value was given
29
+ return @component_instance.class.class_store.to_h[key]
30
+ end
31
+
32
+ # otherwise return nil
33
+ return nil
34
+ end
35
+ end
36
+
37
+ def dispatch(action)
38
+ Isomorfeus.store.dispatch(action)
39
+ end
40
+
41
+ def subscribe(&block)
42
+ Isomorfeus.store.subscribe(&block)
43
+ end
44
+
45
+ def unsubscribe(unsubscriber)
46
+ `unsubscriber()`
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,40 @@
1
+ module React
2
+ module ReduxComponent
3
+ class ComponentClassStoreDefaults
4
+ def initialize(state, component_name)
5
+ @state = state
6
+ @component_name = component_name
7
+ if @state.isomorfeus_store
8
+ @state.isomorfeus_store.merge!(component_class_state: { @component_name => {} })
9
+ else
10
+ @state.isomorfeus_store = { component_class_state: { @component_name => {} } }
11
+ end
12
+ end
13
+
14
+ def method_missing(key, *args, &block)
15
+ if `args.length > 0`
16
+ # set initial class state
17
+ key = key.chop if `key.endsWith('=')`
18
+ @state.isomorfeus_store[:component_class_state][@component_name][key] = args[0]
19
+ current_state = Isomorfeus.store.get_state
20
+ if !(current_state[:component_class_state].has_key?(@component_name) && current_state[:component_class_state][@component_name].has_key?(key))
21
+ Isomorfeus.store.dispatch(type: 'COMPONENT_CLASS_STATE', class: @component_name, name: key, value: args[0])
22
+ end
23
+ else
24
+ # get class state
25
+
26
+ # check if we have a component local state value
27
+
28
+ if @state.isomorfeus_store[:component_class_state][@component_name].has_key?(key)
29
+ return @state.isomorfeus_store[:component_class_state][@component_name][key]
30
+ end
31
+ end
32
+ nil
33
+ end
34
+
35
+ def to_h
36
+ @state.isomorfeus_store[:component_class_state][@component_name]
37
+ end
38
+ end
39
+ end
40
+ end