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.
- checksums.yaml +7 -0
- data/Gemfile +1 -0
- data/README.md +620 -0
- data/isomorfeus-react.gemspec +23 -0
- data/lib/isomorfeus-react.rb +131 -0
- data/lib/isomorfeus/config.rb +84 -0
- data/lib/isomorfeus/top_level.rb +48 -0
- data/lib/isomorfeus/view_helpers.rb +38 -0
- data/lib/lucid_app/api.rb +22 -0
- data/lib/lucid_app/base.rb +7 -0
- data/lib/lucid_app/context.rb +7 -0
- data/lib/lucid_app/mixin.rb +17 -0
- data/lib/lucid_app/native_component_constructor.rb +70 -0
- data/lib/lucid_component/api.rb +97 -0
- data/lib/lucid_component/base.rb +7 -0
- data/lib/lucid_component/event_handler.rb +17 -0
- data/lib/lucid_component/initializer.rb +12 -0
- data/lib/lucid_component/mixin.rb +17 -0
- data/lib/lucid_component/native_component_constructor.rb +131 -0
- data/lib/react.rb +147 -0
- data/lib/react/active_support_support.rb +13 -0
- data/lib/react/component/api.rb +226 -0
- data/lib/react/component/base.rb +9 -0
- data/lib/react/component/elements.rb +78 -0
- data/lib/react/component/event_handler.rb +19 -0
- data/lib/react/component/features.rb +47 -0
- data/lib/react/component/history.rb +36 -0
- data/lib/react/component/initializer.rb +11 -0
- data/lib/react/component/location.rb +15 -0
- data/lib/react/component/match.rb +31 -0
- data/lib/react/component/mixin.rb +19 -0
- data/lib/react/component/native_component_constructor.rb +76 -0
- data/lib/react/component/native_component_validate_prop.rb +37 -0
- data/lib/react/component/props.rb +49 -0
- data/lib/react/component/resolution.rb +71 -0
- data/lib/react/component/should_component_update.rb +14 -0
- data/lib/react/component/state.rb +52 -0
- data/lib/react/component/unsafe_api.rb +33 -0
- data/lib/react/context_wrapper.rb +47 -0
- data/lib/react/function_component/creator.rb +47 -0
- data/lib/react/function_component/resolution.rb +61 -0
- data/lib/react/function_component/runner.rb +19 -0
- data/lib/react/native_constant_wrapper.rb +34 -0
- data/lib/react/pure_component/base.rb +9 -0
- data/lib/react/pure_component/mixin.rb +17 -0
- data/lib/react/redux_component/api.rb +132 -0
- data/lib/react/redux_component/app_store_defaults.rb +38 -0
- data/lib/react/redux_component/app_store_proxy.rb +46 -0
- data/lib/react/redux_component/base.rb +9 -0
- data/lib/react/redux_component/class_store_proxy.rb +50 -0
- data/lib/react/redux_component/component_class_store_defaults.rb +40 -0
- data/lib/react/redux_component/component_instance_store_defaults.rb +41 -0
- data/lib/react/redux_component/initializer.rb +14 -0
- data/lib/react/redux_component/instance_store_proxy.rb +50 -0
- data/lib/react/redux_component/mixin.rb +18 -0
- data/lib/react/redux_component/native_component_constructor.rb +119 -0
- data/lib/react/redux_component/reducers.rb +53 -0
- data/lib/react/ref.rb +19 -0
- data/lib/react/synthetic_event.rb +53 -0
- data/lib/react/version.rb +3 -0
- data/lib/react_dom.rb +31 -0
- data/lib/react_dom_server.rb +17 -0
- 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,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,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
|