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,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
|