isomorfeus-react 16.5.1

Sign up to get free protection for your applications and to get access to all the features.
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