isomorfeus-react 16.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,97 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module API
|
3
|
+
def self.included(base)
|
4
|
+
base.instance_exec do
|
5
|
+
def app_store
|
6
|
+
@default_app_store_defined = true
|
7
|
+
@default_app_store ||= ::React::ReduxComponent::AppStoreDefaults.new(default_props)
|
8
|
+
end
|
9
|
+
|
10
|
+
def class_store
|
11
|
+
@default_class_store_defined = true
|
12
|
+
@default_class_store ||= ::React::ReduxComponent::ComponentClassStoreDefaults.new(default_props, self.to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
def store
|
16
|
+
@default_instance_store_defined = true
|
17
|
+
@default_class_store ||= ::React::ReduxComponent::ComponentInstanceStoreDefaults.new(default_props, self.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def prop(name, options = `null`)
|
21
|
+
name = `Opal.React.lower_camelize(name)`
|
22
|
+
if options
|
23
|
+
if options.has_key?(:default)
|
24
|
+
%x{
|
25
|
+
if (typeof self.lucid_react_component.defaultProps == "undefined") {
|
26
|
+
self.lucid_react_component.defaultProps = { isomorfeus_store: Opal.Hash.$new() };
|
27
|
+
}
|
28
|
+
self.lucid_react_component.defaultProps[name] = options.$fetch("default");
|
29
|
+
}
|
30
|
+
end
|
31
|
+
if options.has_key?(:class)
|
32
|
+
%x{
|
33
|
+
if (typeof self.lucid_react_component.propTypes == "undefined") {
|
34
|
+
self.lucid_react_component.propTypes = {};
|
35
|
+
self.lucid_react_component.propValidations = {};
|
36
|
+
self.lucid_react_component.propValidations[name] = {};
|
37
|
+
}
|
38
|
+
self.lucid_react_component.propTypes[name] = self.lucid_react_component.prototype.validateProp;
|
39
|
+
self.lucid_react_component.propValidations[name].ruby_class = options.$fetch("class");
|
40
|
+
}
|
41
|
+
elsif options.has_key?(:is_a)
|
42
|
+
%x{
|
43
|
+
if (typeof self.lucid_react_component.propTypes == "undefined") {
|
44
|
+
self.lucid_react_component.propTypes = {};
|
45
|
+
self.lucid_react_component.propValidations = {};
|
46
|
+
self.lucid_react_component.propValidations[name] = {};
|
47
|
+
}
|
48
|
+
self.lucid_react_component.propTypes[name] = self.lucid_react_component.prototype.validateProp;
|
49
|
+
self.lucid_react_component.propValidations[name].is_a = options.$fetch("is_a");
|
50
|
+
}
|
51
|
+
end
|
52
|
+
if options.has_key?(:required)
|
53
|
+
%x{
|
54
|
+
if (typeof self.lucid_react_component.propTypes == "undefined") {
|
55
|
+
self.lucid_react_component.propTypes = {};
|
56
|
+
self.lucid_react_component.propValidations = {};
|
57
|
+
self.lucid_react_component.propValidations[name] = {};
|
58
|
+
}
|
59
|
+
self.lucid_react_component.propTypes[name] = self.lucid_react_component.prototype.validateProp;
|
60
|
+
self.lucid_react_component.propValidations[name].required = options.$fetch("required");
|
61
|
+
}
|
62
|
+
elsif !options.has_key?(:default)
|
63
|
+
%x{
|
64
|
+
if (typeof self.lucid_react_component.propTypes == "undefined") {
|
65
|
+
self.lucid_react_component.propTypes = {};
|
66
|
+
self.lucid_react_component.propValidations = {};
|
67
|
+
}
|
68
|
+
self.lucid_react_component.propTypes[name] = self.lucid_react_component.prototype.validateProp;
|
69
|
+
self.lucid_react_component.propValidations[name].required = true;
|
70
|
+
}
|
71
|
+
end
|
72
|
+
else
|
73
|
+
%x{
|
74
|
+
if (typeof self.lucid_react_component.propTypes == "undefined") {
|
75
|
+
self.lucid_react_component.propTypes = {};
|
76
|
+
self.lucid_react_component.propValidations = {};
|
77
|
+
self.lucid_react_component.propValidations[name] = {};
|
78
|
+
}
|
79
|
+
self.lucid_react_component.propTypes[name] = self.lucid_react_component.prototype.validateProp;
|
80
|
+
self.lucid_react_component.propValidations[name].required = options.$fetch("required");
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def default_props
|
86
|
+
return @default_props if @default_props
|
87
|
+
%x{
|
88
|
+
if (typeof self.lucid_react_component.defaultProps == "undefined") {
|
89
|
+
self.lucid_react_component.defaultProps = { isomorfeus_store: Opal.Hash.$new() };
|
90
|
+
}
|
91
|
+
}
|
92
|
+
@default_props = React::Component::Props.new(`self.lucid_react_component.defaultProps`)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module EventHandler
|
3
|
+
def event_handlers
|
4
|
+
@event_handlers ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def event_handler(name, &block)
|
8
|
+
event_handlers << name
|
9
|
+
%x{
|
10
|
+
self.lucid_react_component.prototype[name] = function(event, info) {
|
11
|
+
#{ruby_event = ::React::SyntheticEvent.new(`event`)};
|
12
|
+
#{`this.__ruby_instance`.instance_exec(ruby_event, `info`, &block)};
|
13
|
+
}
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module Initializer
|
3
|
+
def initialize(native_component)
|
4
|
+
@native = native_component
|
5
|
+
@app_store = ::React::ReduxComponent::AppStoreProxy.new(self, 'props')
|
6
|
+
@class_store = ::React::ReduxComponent::ClassStoreProxy.new(self, 'props')
|
7
|
+
@props = ::React::Component::Props.new(@native.JS[:props])
|
8
|
+
@state = ::React::Component::State.new(@native)
|
9
|
+
@store = ::React::ReduxComponent::InstanceStoreProxy.new(self, 'props')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module Mixin
|
3
|
+
def self.included(base)
|
4
|
+
base.include(::Native::Wrapper)
|
5
|
+
base.extend(::LucidComponent::NativeComponentConstructor)
|
6
|
+
base.extend(::React::Component::NativeComponentValidateProp)
|
7
|
+
base.extend(::LucidComponent::EventHandler)
|
8
|
+
base.include(::React::Component::Elements)
|
9
|
+
base.include(::React::Component::API)
|
10
|
+
base.include(::React::ReduxComponent::API)
|
11
|
+
base.include(::LucidComponent::API)
|
12
|
+
base.include(::LucidComponent::Initializer)
|
13
|
+
base.include(::React::Component::Features)
|
14
|
+
base.include(::React::Component::Resolution)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module LucidComponent
|
2
|
+
module NativeComponentConstructor
|
3
|
+
# for should_component_update we apply ruby semantics for comparing props
|
4
|
+
# to do so, we convert the props to ruby hashes and then compare
|
5
|
+
# this makes sure, that for example rubys Nil object gets handled properly
|
6
|
+
def self.extended(base)
|
7
|
+
component_name = base.to_s
|
8
|
+
# language=JS
|
9
|
+
%x{
|
10
|
+
base.react_component = function(props) {
|
11
|
+
return React.createElement(LucidApplicationContext.Consumer, null, function(store) {
|
12
|
+
var store_props = Object.assign({}, props, { isomorfeus_store: store });
|
13
|
+
return React.createElement(base.lucid_react_component, store_props);
|
14
|
+
});
|
15
|
+
}
|
16
|
+
base.lucid_react_component = class extends React.Component {
|
17
|
+
constructor(props) {
|
18
|
+
super(props);
|
19
|
+
if (base.$default_state_defined()) {
|
20
|
+
this.state = base.$state().$to_n();
|
21
|
+
} else {
|
22
|
+
this.state = {};
|
23
|
+
};
|
24
|
+
this.__ruby_instance = base.$new(this);
|
25
|
+
this.__object_id = this.__ruby_instance.$object_id().$to_s();
|
26
|
+
if (!this.state.component_state) {
|
27
|
+
this.state.component_state = {};
|
28
|
+
this.state.component_state[this.__object_id] = {};
|
29
|
+
};
|
30
|
+
var event_handlers = #{base.event_handlers};
|
31
|
+
for (var i = 0; i < event_handlers.length; i++) {
|
32
|
+
this[event_handlers[i]] = this[event_handlers[i]].bind(this);
|
33
|
+
}
|
34
|
+
var defined_refs = #{base.defined_refs};
|
35
|
+
for (var ref in defined_refs) {
|
36
|
+
if (defined_refs[ref] != null) {
|
37
|
+
this[ref] = function(element) {
|
38
|
+
#{`this.__ruby_instance`.instance_exec(React::Ref.new(`element`), `defined_refs[ref]`)}
|
39
|
+
}
|
40
|
+
this[ref] = this[ref].bind(this);
|
41
|
+
} else {
|
42
|
+
this[ref] = React.createRef();
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
data_access() {
|
47
|
+
return this.props.isomorfeus_store
|
48
|
+
}
|
49
|
+
static get displayName() {
|
50
|
+
return #{component_name};
|
51
|
+
}
|
52
|
+
register_used_store_path(path) {
|
53
|
+
this.used_store_paths.push(path);
|
54
|
+
}
|
55
|
+
shouldComponentUpdate(next_props, next_state) {
|
56
|
+
var next_props_keys = Object.keys(next_props);
|
57
|
+
var this_props_keys = Object.keys(this.props);
|
58
|
+
if (next_props_keys.length !== this_props_keys.length) { return true; }
|
59
|
+
|
60
|
+
var next_state_keys = Object.keys(next_state);
|
61
|
+
var this_state_keys = Object.keys(this.state);
|
62
|
+
if (next_state_keys.length !== this_state_keys.length) { return true; }
|
63
|
+
|
64
|
+
for (var property in next_props) {
|
65
|
+
if (property === "isomorfeus_store") {
|
66
|
+
var res = this.scu_for_used_store_paths(this, this.state.isomorfeus_store, next_state.isomorfeus_store);
|
67
|
+
if (res) { return true; }
|
68
|
+
}
|
69
|
+
if (next_props.hasOwnProperty(property)) {
|
70
|
+
if (!this.props.hasOwnProperty(property)) { return true; };
|
71
|
+
if (property == "children") { if (next_props.children !== this.props.children) { return true; }}
|
72
|
+
else if (typeof next_props[property] !== "undefined" && typeof next_props[property]['$!='] !== "undefined" && typeof this.props[property] !== "undefined" && typeof this.props[property]['$!='] !== "undefined") {
|
73
|
+
if (#{ !! (`next_props[property]` != `this.props[property]`) }) { return true; };
|
74
|
+
} else if (next_props[property] !== this.props[property]) { return true; };
|
75
|
+
}
|
76
|
+
}
|
77
|
+
for (var property in next_state) {
|
78
|
+
if (next_state.hasOwnProperty(property)) {
|
79
|
+
if (!this.state.hasOwnProperty(property)) { return true; };
|
80
|
+
if (typeof next_state[property]['$!='] !== "undefined" && typeof this.state[property]['$!='] !== "undefined") {
|
81
|
+
if (#{ !! (`next_state[property]` != `this.state[property]`) }) { return true };
|
82
|
+
} else if (next_state[property] !== this.state[property]) { return true };
|
83
|
+
}
|
84
|
+
}
|
85
|
+
return false;
|
86
|
+
}
|
87
|
+
scu_for_used_store_paths(self, current_state, next_state) {
|
88
|
+
var unique_used_store_paths = self.used_store_paths.filter(function(elem, pos) {
|
89
|
+
return (self.used_store_paths.indexOf(elem) === pos);
|
90
|
+
});
|
91
|
+
var used_length = unique_used_store_paths.length;
|
92
|
+
var store_path;
|
93
|
+
var current_value;
|
94
|
+
var next_value;
|
95
|
+
for (var i = 0; i < used_length; i++) {
|
96
|
+
store_path = unique_used_store_paths[i];
|
97
|
+
current_value = store_path.reduce(function(prev, curr) { return prev && prev[curr]; }, current_state);
|
98
|
+
next_value = store_path.reduce(function(prev, curr) { return prev && prev[curr]; }, next_state);
|
99
|
+
if (current_value !== next_value) { return true; };
|
100
|
+
}
|
101
|
+
return false;
|
102
|
+
}
|
103
|
+
validateProp(props, propName, componentName) {
|
104
|
+
if (propName === "isomorfeus_store") { return null };
|
105
|
+
var prop_data = base.lucid_react_component.propValidations[propName];
|
106
|
+
if (!prop_data) { return true; };
|
107
|
+
var value = props[propName];
|
108
|
+
var result;
|
109
|
+
if (typeof prop_data.ruby_class != "undefined") {
|
110
|
+
result = (value.$class() == prop_data.ruby_class);
|
111
|
+
if (!result) {
|
112
|
+
return new Error('Invalid prop ' + propName + '! Expected ' + prop_data.ruby_class.$to_s() + ' but was ' + value.$class().$to_s() + '!');
|
113
|
+
}
|
114
|
+
} else if (typeof prop_data.is_a != "undefined") {
|
115
|
+
result = value["$is_a?"](prop_data.is_a);
|
116
|
+
if (!result) {
|
117
|
+
return new Error('Invalid prop ' + propName + '! Expected a child of ' + prop_data.is_a.$to_s() + '!');
|
118
|
+
}
|
119
|
+
}
|
120
|
+
if (typeof prop_data.required != "undefined") {
|
121
|
+
if (prop_data.required && (typeof props[propName] == "undefined")) {
|
122
|
+
return new Error('Prop ' + propName + ' is required but not given!');
|
123
|
+
}
|
124
|
+
}
|
125
|
+
return null;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/react.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
module React
|
2
|
+
# to_native_react_props: the native_component params is used for event handlers, it keeps the event handlers
|
3
|
+
# it does not need to be component, can be a object with the event handlers
|
4
|
+
# language=JS
|
5
|
+
%x{
|
6
|
+
self.render_buffer = [];
|
7
|
+
|
8
|
+
self.lower_camelize = function(snake_cased_word) {
|
9
|
+
var parts = snake_cased_word.split('_');
|
10
|
+
var res = parts[0];
|
11
|
+
|
12
|
+
for (var i = 1; i < parts.length; i++) {
|
13
|
+
res += parts[i][0].toUpperCase() + parts[i].slice(1);
|
14
|
+
}
|
15
|
+
return res;
|
16
|
+
}
|
17
|
+
|
18
|
+
self.to_native_react_props = function(ruby_style_props) {
|
19
|
+
var result = {};
|
20
|
+
var keys = ruby_style_props.$keys();
|
21
|
+
var keys_length = keys.length;
|
22
|
+
for (var i = 0; i < keys_length; i++) {
|
23
|
+
if (keys[i].startsWith("on_")) {
|
24
|
+
var handler = ruby_style_props['$[]'](keys[i]);
|
25
|
+
if (typeof handler === "function") {
|
26
|
+
result[Opal.React.lower_camelize(keys[i])] = handler;
|
27
|
+
} else {
|
28
|
+
var active_component = Opal.React.active_component();
|
29
|
+
result[Opal.React.lower_camelize(keys[i])] = active_component[handler];
|
30
|
+
}
|
31
|
+
} else if (keys[i].startsWith("aria_")) {
|
32
|
+
result[keys[i].replace("_", "-")] = ruby_style_props['$[]'](keys[i]);
|
33
|
+
} else {
|
34
|
+
result[Opal.React.lower_camelize(keys[i])] = ruby_style_props['$[]'](keys[i]);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
return result;
|
38
|
+
}
|
39
|
+
|
40
|
+
self.internal_render = function(component, props, block) {
|
41
|
+
var children;
|
42
|
+
var block_result;
|
43
|
+
var react_element;
|
44
|
+
|
45
|
+
if (block !== nil) {
|
46
|
+
Opal.React.render_buffer.push([]);
|
47
|
+
block_result = block.$call();
|
48
|
+
if (block_result && (block_result !== nil && (typeof block_result === "string" || typeof block_result.$$typeof === "symbol" ||
|
49
|
+
(typeof block_result.constructor !== "undefined" && block_result.constructor === Array && block_result[0] && typeof block_result[0].$$typeof === "symbol")
|
50
|
+
))) {
|
51
|
+
Opal.React.render_buffer[Opal.React.render_buffer.length - 1].push(block_result);
|
52
|
+
}
|
53
|
+
children = Opal.React.render_buffer.pop();
|
54
|
+
if (children.length == 1) { children = children[0]; }
|
55
|
+
else if (children.length == 0) { children = null; }
|
56
|
+
}
|
57
|
+
react_element = React.createElement(component, props, children);
|
58
|
+
Opal.React.render_buffer[Opal.React.render_buffer.length - 1].push(react_element);
|
59
|
+
};
|
60
|
+
|
61
|
+
self.active_components = [];
|
62
|
+
|
63
|
+
self.active_component = function() {
|
64
|
+
var length = Opal.React.active_components.length;
|
65
|
+
if (length === 0) { return null; };
|
66
|
+
return Opal.React.active_components[length-1];
|
67
|
+
};
|
68
|
+
|
69
|
+
self.active_redux_components = [];
|
70
|
+
|
71
|
+
self.active_redux_component = function() {
|
72
|
+
var length = Opal.React.active_redux_components.length;
|
73
|
+
if (length === 0) { return null; };
|
74
|
+
return Opal.React.active_redux_components[length-1];
|
75
|
+
};
|
76
|
+
}
|
77
|
+
|
78
|
+
def self.clone_element(ruby_react_element, props = nil, children = nil, &block)
|
79
|
+
block_result = `null`
|
80
|
+
if block_given?
|
81
|
+
block_result = block.call
|
82
|
+
block_result = `null` unless block_result
|
83
|
+
end
|
84
|
+
native_props = props ? `Opal.React.to_native_react_props(props)` : `null`
|
85
|
+
`React.cloneElement(ruby_react_element.$to_n(), native_props, block_result)`
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.create_context(const_name, default_value)
|
89
|
+
%x{
|
90
|
+
Opal.global[const_name] = React.createContext(default_value);
|
91
|
+
var new_const = #{React::ContextWrapper.new(`Opal.global[const_name]`)};
|
92
|
+
#{Object.const_set(const_name, `new_const`)};
|
93
|
+
return new_const;
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.create_element(type, props = nil, children = nil, &block)
|
98
|
+
%x{
|
99
|
+
var component = null;
|
100
|
+
var block_result = null;
|
101
|
+
var native_props = null;
|
102
|
+
|
103
|
+
if (typeof type.react_component == "function") {
|
104
|
+
component = type.react_component;
|
105
|
+
}
|
106
|
+
else {
|
107
|
+
component = type;
|
108
|
+
}
|
109
|
+
|
110
|
+
Opal.React.render_buffer.push([]);
|
111
|
+
#{
|
112
|
+
native_props = `Opal.React.to_native_react_props(props)` if props;
|
113
|
+
}
|
114
|
+
if (block !== nil) {
|
115
|
+
block_result = block.$call()
|
116
|
+
if (block_result && (block_result !== nil && (typeof block_result === "string" || typeof block_result.$$typeof === "symbol" ||
|
117
|
+
(typeof block_result.constructor !== "undefined" && block_result.constructor === Array && block_result[0] && typeof block_result[0].$$typeof === "symbol")
|
118
|
+
))) {
|
119
|
+
Opal.React.render_buffer[Opal.React.render_buffer.length - 1].push(block_result);
|
120
|
+
}
|
121
|
+
children = Opal.React.render_buffer.pop()
|
122
|
+
if (children.length == 1) { children = children[0]; }
|
123
|
+
else if (children.length == 0) { children = null; }
|
124
|
+
}
|
125
|
+
return React.createElement(component, native_props, children);
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.create_factory(type)
|
130
|
+
native_function = `React.createFactory(type)`
|
131
|
+
proc { `native_function.call()` }
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
def self.create_ref
|
136
|
+
React::Ref.new(`React.createRef()`)
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.forwardRef(&block)
|
140
|
+
# TODO whats the return here? A React:Element?, doc says a React node, whats that?
|
141
|
+
`React.forwardRef( function(props, ref) { return block.$call().$to_n(); })`
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.isValidElement(react_element)
|
145
|
+
`React.isValidElement(react_element)`
|
146
|
+
end
|
147
|
+
end
|