isomorfeus-react 16.13.11 → 16.13.12
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 +4 -4
- data/README.md +3 -1
- data/lib/isomorfeus/react/config.rb +189 -189
- data/lib/isomorfeus/react/memcached_component_cache.rb +19 -19
- data/lib/isomorfeus/react/redis_component_cache.rb +19 -19
- data/lib/isomorfeus/react/thread_local_component_cache.rb +15 -15
- data/lib/isomorfeus/react_view_helper.rb +231 -231
- data/lib/isomorfeus/top_level.rb +103 -103
- data/lib/isomorfeus/top_level_ssr.rb +42 -42
- data/lib/isomorfeus-react-material-ui.rb +4 -4
- data/lib/isomorfeus-react-native.rb +5 -5
- data/lib/isomorfeus-react-paper.rb +4 -4
- data/lib/isomorfeus-react.rb +120 -120
- data/lib/isomorfeus_react/lucid_app/api.rb +26 -26
- data/lib/isomorfeus_react/lucid_app/base.rb +7 -7
- data/lib/isomorfeus_react/lucid_app/mixin.rb +23 -23
- data/lib/isomorfeus_react/lucid_app/native_component_constructor.rb +48 -48
- data/lib/isomorfeus_react/lucid_app/native_lucid_component_constructor.rb +94 -95
- data/lib/isomorfeus_react/lucid_component/api.rb +75 -75
- data/lib/isomorfeus_react/lucid_component/app_store_proxy.rb +37 -37
- data/lib/isomorfeus_react/lucid_component/base.rb +7 -7
- data/lib/isomorfeus_react/lucid_component/class_store_proxy.rb +44 -44
- data/lib/isomorfeus_react/lucid_component/initializer.rb +14 -14
- data/lib/isomorfeus_react/lucid_component/instance_store_proxy.rb +44 -44
- data/lib/isomorfeus_react/lucid_component/mixin.rb +22 -22
- data/lib/isomorfeus_react/lucid_component/native_component_constructor.rb +35 -35
- data/lib/isomorfeus_react/lucid_component/native_lucid_component_constructor.rb +82 -83
- data/lib/isomorfeus_react/lucid_component/styles_api.rb +34 -34
- data/lib/isomorfeus_react/lucid_func/base.rb +7 -7
- data/lib/isomorfeus_react/lucid_func/initializer.rb +11 -11
- data/lib/isomorfeus_react/lucid_func/mixin.rb +18 -18
- data/lib/isomorfeus_react/lucid_func/native_component_constructor.rb +81 -81
- data/lib/isomorfeus_react/react/function_component/api.rb +105 -105
- data/lib/isomorfeus_react/react/function_component/base.rb +8 -8
- data/lib/isomorfeus_react/react/function_component/initializer.rb +10 -10
- data/lib/isomorfeus_react/react/function_component/mixin.rb +17 -17
- data/lib/isomorfeus_react/react/function_component/native_component_constructor.rb +48 -48
- data/lib/isomorfeus_react/react/memo_component/base.rb +8 -8
- data/lib/isomorfeus_react/react/memo_component/mixin.rb +17 -17
- data/lib/isomorfeus_react/react/memo_component/native_component_constructor.rb +49 -49
- data/lib/isomorfeus_react_material/lucid_material/app/base.rb +8 -8
- data/lib/isomorfeus_react_material/lucid_material/app/mixin.rb +20 -20
- data/lib/isomorfeus_react_material/lucid_material/app/native_component_constructor.rb +50 -50
- data/lib/isomorfeus_react_material/lucid_material/component/base.rb +9 -9
- data/lib/isomorfeus_react_material/lucid_material/component/mixin.rb +19 -19
- data/lib/isomorfeus_react_material/lucid_material/component/native_component_constructor.rb +36 -36
- data/lib/isomorfeus_react_material/lucid_material/func/base.rb +9 -9
- data/lib/isomorfeus_react_material/lucid_material/func/mixin.rb +15 -15
- data/lib/isomorfeus_react_material/lucid_material/func/native_component_constructor.rb +83 -83
- data/lib/isomorfeus_react_paper/lucid_paper/app/base.rb +9 -9
- data/lib/isomorfeus_react_paper/lucid_paper/app/mixin.rb +19 -19
- data/lib/isomorfeus_react_paper/lucid_paper/app/native_component_constructor.rb +32 -32
- data/lib/isomorfeus_react_paper/lucid_paper/component/base.rb +9 -9
- data/lib/isomorfeus_react_paper/lucid_paper/component/mixin.rb +18 -18
- data/lib/isomorfeus_react_paper/lucid_paper/component/native_component_constructor.rb +25 -25
- data/lib/isomorfeus_react_paper/lucid_paper/func/base.rb +9 -9
- data/lib/isomorfeus_react_paper/lucid_paper/func/mixin.rb +14 -14
- data/lib/isomorfeus_react_paper/lucid_paper/func/native_component_constructor.rb +71 -71
- data/lib/lucid_app/context.rb +7 -7
- data/lib/lucid_prop_declaration/mixin.rb +126 -126
- data/lib/react/children.rb +34 -34
- data/lib/react/component/api.rb +134 -134
- data/lib/react/component/base.rb +8 -8
- data/lib/react/component/callbacks.rb +115 -115
- data/lib/react/component/elements.rb +60 -60
- data/lib/react/component/features.rb +48 -48
- data/lib/react/component/history.rb +69 -65
- data/lib/react/component/initializer.rb +11 -11
- data/lib/react/component/location.rb +19 -15
- data/lib/react/component/match.rb +35 -31
- data/lib/react/component/mixin.rb +20 -20
- data/lib/react/component/native_component_constructor.rb +69 -70
- data/lib/react/component/props.rb +83 -83
- data/lib/react/component/resolution.rb +97 -97
- data/lib/react/component/state.rb +58 -54
- data/lib/react/component/styles.rb +66 -66
- data/lib/react/context_wrapper.rb +48 -44
- data/lib/react/native_constant_wrapper.rb +29 -29
- data/lib/react/ref.rb +16 -12
- data/lib/react/synthetic_event.rb +52 -52
- data/lib/react/version.rb +3 -3
- data/lib/react.rb +296 -296
- data/lib/react_dom.rb +41 -41
- data/lib/react_dom_server.rb +18 -18
- data/lib/react_native/component/elements.rb +203 -203
- data/lib/react_native/lucid_app/react_native_component_constructor.rb +51 -51
- data/lib/react_native/lucid_component/react_native_component_constructor.rb +37 -37
- data/lib/react_native/lucid_func/react_native_component_constructor.rb +82 -82
- data/lib/react_native/react.rb +120 -120
- metadata +23 -17
data/lib/react.rb
CHANGED
|
@@ -1,296 +1,296 @@
|
|
|
1
|
-
module React
|
|
2
|
-
%x{
|
|
3
|
-
self.render_buffer = [];
|
|
4
|
-
|
|
5
|
-
self.set_validate_prop = function(component, prop_name) {
|
|
6
|
-
let core = component.react_component;
|
|
7
|
-
if (typeof core.propTypes == "undefined") {
|
|
8
|
-
core.propTypes = {};
|
|
9
|
-
core.propValidations = {};
|
|
10
|
-
core.propValidations[prop_name] = {};
|
|
11
|
-
}
|
|
12
|
-
core.propTypes[prop_name] = core.prototype.validateProp;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
self.props_are_equal = function(this_props, next_props) {
|
|
16
|
-
let counter = 0;
|
|
17
|
-
for (var property in next_props) {
|
|
18
|
-
counter++;
|
|
19
|
-
if (next_props.hasOwnProperty(property)) {
|
|
20
|
-
if (!this_props.hasOwnProperty(property)) { return false; };
|
|
21
|
-
if (property === "children") { if (next_props.children !== this_props.children) { return false; }}
|
|
22
|
-
else if (typeof next_props[property] === "object" && next_props[property] !== null && typeof next_props[property]['$!='] === "function" &&
|
|
23
|
-
typeof this_props[property] !== "undefined" && this_props[property] !== null ) {
|
|
24
|
-
if (#{ !! (`next_props[property]` != `this_props[property]`) }) { return false; }
|
|
25
|
-
} else if (next_props[property] !== this_props[property]) { return false; }
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (counter !== Object.keys(this_props).length) { return false; }
|
|
29
|
-
return true;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
self.state_is_not_equal = function(this_state, next_state) {
|
|
33
|
-
let counter = 0;
|
|
34
|
-
for (var property in next_state) {
|
|
35
|
-
counter++;
|
|
36
|
-
if (next_state.hasOwnProperty(property)) {
|
|
37
|
-
if (!this_state.hasOwnProperty(property)) { return true; };
|
|
38
|
-
if (typeof next_state[property] === "object" && next_state[property] !== null && typeof next_state[property]['$!='] === "function" &&
|
|
39
|
-
typeof this_state[property] !== "undefined" && this_state[property] !== null) {
|
|
40
|
-
if (#{ !! (`next_state[property]` != `this_state[property]`) }) { return true }
|
|
41
|
-
} else if (next_state[property] !== this_state[property]) { return true }
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (counter !== Object.keys(this_state).length) { return true; }
|
|
45
|
-
return false;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
self.lower_camelize = function(snake_cased_word) {
|
|
49
|
-
if (self.prop_dictionary[snake_cased_word]) { return self.prop_dictionary[snake_cased_word]; }
|
|
50
|
-
let parts = snake_cased_word.split('_');
|
|
51
|
-
let res = parts[0];
|
|
52
|
-
for (let i = 1; i < parts.length; i++) {
|
|
53
|
-
res += parts[i][0].toUpperCase() + parts[i].slice(1);
|
|
54
|
-
}
|
|
55
|
-
self.prop_dictionary[snake_cased_word] = res;
|
|
56
|
-
return res;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
self.native_element_or_component_to_ruby = function (element) {
|
|
60
|
-
if (typeof element.__ruby_instance !== 'undefined') { return element.__ruby_instance }
|
|
61
|
-
if (element instanceof Element || element instanceof Node) { return #{Browser::Element.new(`element`)} }
|
|
62
|
-
return element;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
self.native_to_ruby_event = function(event) {
|
|
66
|
-
if (event.hasOwnProperty('target')) { return #{::React::SyntheticEvent.new(`event`)}; }
|
|
67
|
-
else if (Array.isArray(event)) { return event; }
|
|
68
|
-
else { return Opal.Hash.$new(event); }
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
self.internal_prepare_args_and_render = function(component, args, block) {
|
|
72
|
-
const operain = self.internal_render;
|
|
73
|
-
if (args.length > 0) {
|
|
74
|
-
let last_arg = args[args.length - 1];
|
|
75
|
-
if (last_arg && last_arg.constructor === String) {
|
|
76
|
-
if (args.length === 1) { return operain(component, null, last_arg, null); }
|
|
77
|
-
else { operain(component, args[0], last_arg, null); }
|
|
78
|
-
} else { operain(component, args[0], null, block); }
|
|
79
|
-
} else { operain(component, null, null, block); }
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
self.active_components = [];
|
|
83
|
-
|
|
84
|
-
self.active_component = function() {
|
|
85
|
-
let length = self.active_components.length;
|
|
86
|
-
if (length === 0) { return null; };
|
|
87
|
-
return self.active_components[length-1];
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
self.active_redux_components = [];
|
|
91
|
-
|
|
92
|
-
self.active_redux_component = function() {
|
|
93
|
-
let length = self.active_redux_components.length;
|
|
94
|
-
if (length === 0) { return null; };
|
|
95
|
-
return self.active_redux_components[length-1];
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
function isObject(obj) { return (obj && typeof obj === 'object'); }
|
|
99
|
-
|
|
100
|
-
self.merge_deep = function(one, two) {
|
|
101
|
-
return [one, two].reduce(function(pre, obj) {
|
|
102
|
-
Object.keys(obj).forEach(function(key){
|
|
103
|
-
let pVal = pre[key];
|
|
104
|
-
let oVal = obj[key];
|
|
105
|
-
if (Array.isArray(pVal) && Array.isArray(oVal)) {
|
|
106
|
-
pre[key] = pVal.concat.apply(this, oVal);
|
|
107
|
-
} else if (isObject(pVal) && isObject(oVal)) {
|
|
108
|
-
pre[key] = self.merge_deep(pVal, oVal);
|
|
109
|
-
} else {
|
|
110
|
-
pre[key] = oVal;
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
return pre;
|
|
114
|
-
}, {});
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if on_browser? || on_ssr?
|
|
119
|
-
%x{
|
|
120
|
-
self.prop_dictionary = {};
|
|
121
|
-
|
|
122
|
-
self.to_native_react_props = function(ruby_style_props) {
|
|
123
|
-
let result = {};
|
|
124
|
-
let keys = ruby_style_props.$$keys;
|
|
125
|
-
let keys_length = keys.length;
|
|
126
|
-
let key = '';
|
|
127
|
-
for (let i = 0; i < keys_length; i++) {
|
|
128
|
-
key = keys[i];
|
|
129
|
-
let value = ruby_style_props.$$smap[key];
|
|
130
|
-
if (key[0] === 'o' && key[1] === 'n' && key[2] === '_') {
|
|
131
|
-
let type = typeof value;
|
|
132
|
-
if (type === "function") {
|
|
133
|
-
let active_c = self.active_component();
|
|
134
|
-
result[self.lower_camelize(key)] = function(event, info) {
|
|
135
|
-
let ruby_event = self.native_to_ruby_event(event);
|
|
136
|
-
#{`active_c.__ruby_instance`.instance_exec(`ruby_event`, `info`, &`value`)};
|
|
137
|
-
}
|
|
138
|
-
} else if (type === "object" && typeof value.m === "object" && typeof value.m.$call === "function" ) {
|
|
139
|
-
if (!value.react_event_handler_function) {
|
|
140
|
-
value.react_event_handler_function = function(event, info) {
|
|
141
|
-
let ruby_event = self.native_to_ruby_event(event);
|
|
142
|
-
if (value.a.length > 0) { value.m.$call.apply(value.m, [ruby_event, info].concat(value.a)); }
|
|
143
|
-
else { value.m.$call(ruby_event, info); }
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
result[self.lower_camelize(key)] = value.react_event_handler_function;
|
|
147
|
-
} else if (type === "string" ) {
|
|
148
|
-
let active_component = self.active_component();
|
|
149
|
-
let method_ref;
|
|
150
|
-
let method_name = '$' + value;
|
|
151
|
-
if (typeof active_component[method_name] === "function") {
|
|
152
|
-
// got a ruby instance
|
|
153
|
-
if (active_component.native && active_component.native.method_refs && active_component.native.method_refs[value]) { method_ref = active_component.native.method_refs[value]; } // ruby instance with native
|
|
154
|
-
else if (active_component.method_refs && active_component.method_refs[value]) { method_ref = active_component.method_refs[value]; } // ruby function component
|
|
155
|
-
else { method_ref = active_component.$method_ref(value); } // create the ref
|
|
156
|
-
} else if (typeof active_component.__ruby_instance[method_name] === "function") {
|
|
157
|
-
// got a native instance
|
|
158
|
-
if (active_component.method_refs && active_component.method_refs[value]) { method_ref = active_component.method_refs[value]; }
|
|
159
|
-
else { method_ref = active_component.__ruby_instance.$method_ref(value); } // create ref for native
|
|
160
|
-
}
|
|
161
|
-
if (method_ref) {
|
|
162
|
-
if (!method_ref.react_event_handler_function) {
|
|
163
|
-
method_ref.react_event_handler_function = function(event, info) {
|
|
164
|
-
let ruby_event = self.native_to_ruby_event(event);
|
|
165
|
-
method_ref.m.$call(ruby_event, info)
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
result[self.lower_camelize(key)] = method_ref.react_event_handler_function;
|
|
169
|
-
} else {
|
|
170
|
-
let component_name;
|
|
171
|
-
if (active_component.__ruby_instance) { component_name = active_component.__ruby_instance.$to_s(); }
|
|
172
|
-
else { component_name = active_component.$to_s(); }
|
|
173
|
-
#{Isomorfeus.raise_error(message: "Is #{`value`} a valid method of #{`component_name`}? If so then please use: #{`key`}: method_ref(:#{`value`}) within component: #{`component_name`}")}
|
|
174
|
-
}
|
|
175
|
-
} else {
|
|
176
|
-
let active_component = self.active_component();
|
|
177
|
-
let component_name;
|
|
178
|
-
if (active_component.__ruby_instance) { component_name = active_component.__ruby_instance.$to_s(); }
|
|
179
|
-
else { component_name = active_component.$to_s(); }
|
|
180
|
-
#{Isomorfeus.raise_error(message: "Received invalid value for #{`key`} with #{`value`} within component: #{`component_name`}")}
|
|
181
|
-
console.error( + key + " event handler:", value, " within component:", self.active_component());
|
|
182
|
-
}
|
|
183
|
-
} else if (key[0] === 'a' && key.startsWith("aria_")) {
|
|
184
|
-
result[key.replace("_", "-")] = value;
|
|
185
|
-
} else if (key === "style" || key === "theme") {
|
|
186
|
-
if (typeof value.$to_n === "function") { value = value.$to_n() }
|
|
187
|
-
result[key] = value;
|
|
188
|
-
} else {
|
|
189
|
-
result[self.lower_camelize(key)] = value;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return result;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
self.render_block_result = function(block_result) {
|
|
196
|
-
if (block_result.constructor === String || block_result.constructor === Number) {
|
|
197
|
-
Opal.React.render_buffer[Opal.React.render_buffer.length - 1].push(block_result);
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
self.internal_render = function(component, props, string_child, block) {
|
|
202
|
-
const operabu = self.render_buffer;
|
|
203
|
-
let native_props;
|
|
204
|
-
if (props && props !== nil) { native_props = self.to_native_react_props(props); }
|
|
205
|
-
if (string_child) {
|
|
206
|
-
operabu[operabu.length - 1].push(Opal.global.React.createElement(component, native_props, string_child));
|
|
207
|
-
} else if (block && block !== nil) {
|
|
208
|
-
operabu.push([]);
|
|
209
|
-
// console.log("internal_render pushed", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
210
|
-
let block_result = block.$call();
|
|
211
|
-
if (block_result && block_result !== nil) { Opal.React.render_block_result(block_result); }
|
|
212
|
-
// console.log("internal_render popping", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
213
|
-
let children = operabu.pop();
|
|
214
|
-
operabu[operabu.length - 1].push(Opal.global.React.createElement.apply(this, [component, native_props].concat(children)));
|
|
215
|
-
} else {
|
|
216
|
-
operabu[operabu.length - 1].push(Opal.global.React.createElement(component, native_props));
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def self.clone_element(ruby_react_element, props = nil, children = nil, &block)
|
|
223
|
-
block_result = `null`
|
|
224
|
-
if block_given?
|
|
225
|
-
block_result = block.call
|
|
226
|
-
block_result = `null` unless block_result
|
|
227
|
-
end
|
|
228
|
-
native_props = props ? `Opal.React.to_native_react_props(props)` : `null`
|
|
229
|
-
`Opal.global.React.cloneElement(ruby_react_element.$to_n(), native_props, block_result)`
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def self.create_context(const_name, default_value)
|
|
233
|
-
%x{
|
|
234
|
-
Opal.global[const_name] = Opal.global.React.createContext(default_value);
|
|
235
|
-
var new_const = #{React::ContextWrapper.new(`Opal.global[const_name]`)};
|
|
236
|
-
#{Object.const_set(const_name, `new_const`)};
|
|
237
|
-
return new_const;
|
|
238
|
-
}
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
def self.create_element(type, props = nil, children = nil, &block)
|
|
242
|
-
%x{
|
|
243
|
-
const operabu = self.render_buffer;
|
|
244
|
-
let component = null;
|
|
245
|
-
let native_props = null;
|
|
246
|
-
if (typeof type.react_component !== 'undefined') { component = type.react_component; }
|
|
247
|
-
else { component = type; }
|
|
248
|
-
if (block !== nil) {
|
|
249
|
-
operabu.push([]);
|
|
250
|
-
// console.log("create_element pushed", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
251
|
-
let block_result = block.$call();
|
|
252
|
-
if (block_result && block_result !== nil) { Opal.React.render_block_result(block_result); }
|
|
253
|
-
// console.log("create_element popping", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
254
|
-
children = operabu.pop();
|
|
255
|
-
} else if (children === nil) { children = []; }
|
|
256
|
-
else if (typeof children === 'string') { children = [children]; }
|
|
257
|
-
if (props && props !== nil) { native_props = self.to_native_react_props(props); }
|
|
258
|
-
return Opal.global.React.createElement.apply(this, [component, native_props].concat(children));
|
|
259
|
-
}
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
def self.create_factory(type)
|
|
263
|
-
native_function = `Opal.global.React.createFactory(type)`
|
|
264
|
-
proc { `native_function.call()` }
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
def self.create_ref
|
|
268
|
-
React::Ref.new(`Opal.global.React.createRef()`)
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
def self.forwardRef(&block)
|
|
272
|
-
# TODO whats the return here? A React:Element?, doc says a React node, whats that?
|
|
273
|
-
`Opal.global.React.forwardRef( function(props, ref) { return block.$call().$to_n(); })`
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
def self.is_valid_element(react_element)
|
|
277
|
-
`Opal.global.React.isValidElement(react_element)`
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
def self.lazy(import_statement_function)
|
|
281
|
-
`Opal.global.React.lazy(import_statement_function)`
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def self.memo(function_component, &block)
|
|
285
|
-
if block_given?
|
|
286
|
-
%x{
|
|
287
|
-
var fun = function(prev_props, next_props) {
|
|
288
|
-
return #{block.call(::React::Component::Props.new(`{props: prev_props}`), ::React::Component::Props.new(`{props: next_props}`))};
|
|
289
|
-
}
|
|
290
|
-
return Opal.global.React.memo(function_component, fun);
|
|
291
|
-
}
|
|
292
|
-
else
|
|
293
|
-
`Opal.global.React.memo(function_component)`
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
end
|
|
1
|
+
module React
|
|
2
|
+
%x{
|
|
3
|
+
self.render_buffer = [];
|
|
4
|
+
|
|
5
|
+
self.set_validate_prop = function(component, prop_name) {
|
|
6
|
+
let core = component.react_component;
|
|
7
|
+
if (typeof core.propTypes == "undefined") {
|
|
8
|
+
core.propTypes = {};
|
|
9
|
+
core.propValidations = {};
|
|
10
|
+
core.propValidations[prop_name] = {};
|
|
11
|
+
}
|
|
12
|
+
core.propTypes[prop_name] = core.prototype.validateProp;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
self.props_are_equal = function(this_props, next_props) {
|
|
16
|
+
let counter = 0;
|
|
17
|
+
for (var property in next_props) {
|
|
18
|
+
counter++;
|
|
19
|
+
if (next_props.hasOwnProperty(property)) {
|
|
20
|
+
if (!this_props.hasOwnProperty(property)) { return false; };
|
|
21
|
+
if (property === "children") { if (next_props.children !== this_props.children) { return false; }}
|
|
22
|
+
else if (typeof next_props[property] === "object" && next_props[property] !== null && typeof next_props[property]['$!='] === "function" &&
|
|
23
|
+
typeof this_props[property] !== "undefined" && this_props[property] !== null ) {
|
|
24
|
+
if (#{ !! (`next_props[property]` != `this_props[property]`) }) { return false; }
|
|
25
|
+
} else if (next_props[property] !== this_props[property]) { return false; }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (counter !== Object.keys(this_props).length) { return false; }
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
self.state_is_not_equal = function(this_state, next_state) {
|
|
33
|
+
let counter = 0;
|
|
34
|
+
for (var property in next_state) {
|
|
35
|
+
counter++;
|
|
36
|
+
if (next_state.hasOwnProperty(property)) {
|
|
37
|
+
if (!this_state.hasOwnProperty(property)) { return true; };
|
|
38
|
+
if (typeof next_state[property] === "object" && next_state[property] !== null && typeof next_state[property]['$!='] === "function" &&
|
|
39
|
+
typeof this_state[property] !== "undefined" && this_state[property] !== null) {
|
|
40
|
+
if (#{ !! (`next_state[property]` != `this_state[property]`) }) { return true }
|
|
41
|
+
} else if (next_state[property] !== this_state[property]) { return true }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (counter !== Object.keys(this_state).length) { return true; }
|
|
45
|
+
return false;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
self.lower_camelize = function(snake_cased_word) {
|
|
49
|
+
if (self.prop_dictionary[snake_cased_word]) { return self.prop_dictionary[snake_cased_word]; }
|
|
50
|
+
let parts = snake_cased_word.split('_');
|
|
51
|
+
let res = parts[0];
|
|
52
|
+
for (let i = 1; i < parts.length; i++) {
|
|
53
|
+
res += parts[i][0].toUpperCase() + parts[i].slice(1);
|
|
54
|
+
}
|
|
55
|
+
self.prop_dictionary[snake_cased_word] = res;
|
|
56
|
+
return res;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
self.native_element_or_component_to_ruby = function (element) {
|
|
60
|
+
if (typeof element.__ruby_instance !== 'undefined') { return element.__ruby_instance }
|
|
61
|
+
if (element instanceof Element || element instanceof Node) { return #{Browser::Element.new(`element`)} }
|
|
62
|
+
return element;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
self.native_to_ruby_event = function(event) {
|
|
66
|
+
if (event.hasOwnProperty('target')) { return #{::React::SyntheticEvent.new(`event`)}; }
|
|
67
|
+
else if (Array.isArray(event)) { return event; }
|
|
68
|
+
else { return Opal.Hash.$new(event); }
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
self.internal_prepare_args_and_render = function(component, args, block) {
|
|
72
|
+
const operain = self.internal_render;
|
|
73
|
+
if (args.length > 0) {
|
|
74
|
+
let last_arg = args[args.length - 1];
|
|
75
|
+
if (last_arg && last_arg.constructor === String) {
|
|
76
|
+
if (args.length === 1) { return operain(component, null, last_arg, null); }
|
|
77
|
+
else { operain(component, args[0], last_arg, null); }
|
|
78
|
+
} else { operain(component, args[0], null, block); }
|
|
79
|
+
} else { operain(component, null, null, block); }
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
self.active_components = [];
|
|
83
|
+
|
|
84
|
+
self.active_component = function() {
|
|
85
|
+
let length = self.active_components.length;
|
|
86
|
+
if (length === 0) { return null; };
|
|
87
|
+
return self.active_components[length-1];
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
self.active_redux_components = [];
|
|
91
|
+
|
|
92
|
+
self.active_redux_component = function() {
|
|
93
|
+
let length = self.active_redux_components.length;
|
|
94
|
+
if (length === 0) { return null; };
|
|
95
|
+
return self.active_redux_components[length-1];
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
function isObject(obj) { return (obj && typeof obj === 'object'); }
|
|
99
|
+
|
|
100
|
+
self.merge_deep = function(one, two) {
|
|
101
|
+
return [one, two].reduce(function(pre, obj) {
|
|
102
|
+
Object.keys(obj).forEach(function(key){
|
|
103
|
+
let pVal = pre[key];
|
|
104
|
+
let oVal = obj[key];
|
|
105
|
+
if (Array.isArray(pVal) && Array.isArray(oVal)) {
|
|
106
|
+
pre[key] = pVal.concat.apply(this, oVal);
|
|
107
|
+
} else if (isObject(pVal) && isObject(oVal)) {
|
|
108
|
+
pre[key] = self.merge_deep(pVal, oVal);
|
|
109
|
+
} else {
|
|
110
|
+
pre[key] = oVal;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return pre;
|
|
114
|
+
}, {});
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if on_browser? || on_ssr?
|
|
119
|
+
%x{
|
|
120
|
+
self.prop_dictionary = {};
|
|
121
|
+
|
|
122
|
+
self.to_native_react_props = function(ruby_style_props) {
|
|
123
|
+
let result = {};
|
|
124
|
+
let keys = ruby_style_props.$$keys;
|
|
125
|
+
let keys_length = keys.length;
|
|
126
|
+
let key = '';
|
|
127
|
+
for (let i = 0; i < keys_length; i++) {
|
|
128
|
+
key = keys[i];
|
|
129
|
+
let value = ruby_style_props.$$smap[key];
|
|
130
|
+
if (key[0] === 'o' && key[1] === 'n' && key[2] === '_') {
|
|
131
|
+
let type = typeof value;
|
|
132
|
+
if (type === "function") {
|
|
133
|
+
let active_c = self.active_component();
|
|
134
|
+
result[self.lower_camelize(key)] = function(event, info) {
|
|
135
|
+
let ruby_event = self.native_to_ruby_event(event);
|
|
136
|
+
#{`active_c.__ruby_instance`.instance_exec(`ruby_event`, `info`, &`value`)};
|
|
137
|
+
}
|
|
138
|
+
} else if (type === "object" && typeof value.m === "object" && typeof value.m.$call === "function" ) {
|
|
139
|
+
if (!value.react_event_handler_function) {
|
|
140
|
+
value.react_event_handler_function = function(event, info) {
|
|
141
|
+
let ruby_event = self.native_to_ruby_event(event);
|
|
142
|
+
if (value.a.length > 0) { value.m.$call.apply(value.m, [ruby_event, info].concat(value.a)); }
|
|
143
|
+
else { value.m.$call(ruby_event, info); }
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
result[self.lower_camelize(key)] = value.react_event_handler_function;
|
|
147
|
+
} else if (type === "string" ) {
|
|
148
|
+
let active_component = self.active_component();
|
|
149
|
+
let method_ref;
|
|
150
|
+
let method_name = '$' + value;
|
|
151
|
+
if (typeof active_component[method_name] === "function") {
|
|
152
|
+
// got a ruby instance
|
|
153
|
+
if (active_component.native && active_component.native.method_refs && active_component.native.method_refs[value]) { method_ref = active_component.native.method_refs[value]; } // ruby instance with native
|
|
154
|
+
else if (active_component.method_refs && active_component.method_refs[value]) { method_ref = active_component.method_refs[value]; } // ruby function component
|
|
155
|
+
else { method_ref = active_component.$method_ref(value); } // create the ref
|
|
156
|
+
} else if (typeof active_component.__ruby_instance[method_name] === "function") {
|
|
157
|
+
// got a native instance
|
|
158
|
+
if (active_component.method_refs && active_component.method_refs[value]) { method_ref = active_component.method_refs[value]; }
|
|
159
|
+
else { method_ref = active_component.__ruby_instance.$method_ref(value); } // create ref for native
|
|
160
|
+
}
|
|
161
|
+
if (method_ref) {
|
|
162
|
+
if (!method_ref.react_event_handler_function) {
|
|
163
|
+
method_ref.react_event_handler_function = function(event, info) {
|
|
164
|
+
let ruby_event = self.native_to_ruby_event(event);
|
|
165
|
+
method_ref.m.$call(ruby_event, info)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
result[self.lower_camelize(key)] = method_ref.react_event_handler_function;
|
|
169
|
+
} else {
|
|
170
|
+
let component_name;
|
|
171
|
+
if (active_component.__ruby_instance) { component_name = active_component.__ruby_instance.$to_s(); }
|
|
172
|
+
else { component_name = active_component.$to_s(); }
|
|
173
|
+
#{Isomorfeus.raise_error(message: "Is #{`value`} a valid method of #{`component_name`}? If so then please use: #{`key`}: method_ref(:#{`value`}) within component: #{`component_name`}")}
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
let active_component = self.active_component();
|
|
177
|
+
let component_name;
|
|
178
|
+
if (active_component.__ruby_instance) { component_name = active_component.__ruby_instance.$to_s(); }
|
|
179
|
+
else { component_name = active_component.$to_s(); }
|
|
180
|
+
#{Isomorfeus.raise_error(message: "Received invalid value for #{`key`} with #{`value`} within component: #{`component_name`}")}
|
|
181
|
+
console.error( + key + " event handler:", value, " within component:", self.active_component());
|
|
182
|
+
}
|
|
183
|
+
} else if (key[0] === 'a' && key.startsWith("aria_")) {
|
|
184
|
+
result[key.replace("_", "-")] = value;
|
|
185
|
+
} else if (key === "style" || key === "theme") {
|
|
186
|
+
if (typeof value.$to_n === "function") { value = value.$to_n() }
|
|
187
|
+
result[key] = value;
|
|
188
|
+
} else {
|
|
189
|
+
result[self.lower_camelize(key)] = value;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return result;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
self.render_block_result = function(block_result) {
|
|
196
|
+
if (block_result.constructor === String || block_result.constructor === Number) {
|
|
197
|
+
Opal.React.render_buffer[Opal.React.render_buffer.length - 1].push(block_result);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
self.internal_render = function(component, props, string_child, block) {
|
|
202
|
+
const operabu = self.render_buffer;
|
|
203
|
+
let native_props;
|
|
204
|
+
if (props && props !== nil) { native_props = self.to_native_react_props(props); }
|
|
205
|
+
if (string_child) {
|
|
206
|
+
operabu[operabu.length - 1].push(Opal.global.React.createElement(component, native_props, string_child));
|
|
207
|
+
} else if (block && block !== nil) {
|
|
208
|
+
operabu.push([]);
|
|
209
|
+
// console.log("internal_render pushed", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
210
|
+
let block_result = block.$call();
|
|
211
|
+
if (block_result && block_result !== nil) { Opal.React.render_block_result(block_result); }
|
|
212
|
+
// console.log("internal_render popping", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
213
|
+
let children = operabu.pop();
|
|
214
|
+
operabu[operabu.length - 1].push(Opal.global.React.createElement.apply(this, [component, native_props].concat(children)));
|
|
215
|
+
} else {
|
|
216
|
+
operabu[operabu.length - 1].push(Opal.global.React.createElement(component, native_props));
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def self.clone_element(ruby_react_element, props = nil, children = nil, &block)
|
|
223
|
+
block_result = `null`
|
|
224
|
+
if block_given?
|
|
225
|
+
block_result = block.call
|
|
226
|
+
block_result = `null` unless block_result
|
|
227
|
+
end
|
|
228
|
+
native_props = props ? `Opal.React.to_native_react_props(props)` : `null`
|
|
229
|
+
`Opal.global.React.cloneElement(ruby_react_element.$to_n(), native_props, block_result)`
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def self.create_context(const_name, default_value)
|
|
233
|
+
%x{
|
|
234
|
+
Opal.global[const_name] = Opal.global.React.createContext(default_value);
|
|
235
|
+
var new_const = #{React::ContextWrapper.new(`Opal.global[const_name]`)};
|
|
236
|
+
#{Object.const_set(const_name, `new_const`)};
|
|
237
|
+
return new_const;
|
|
238
|
+
}
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def self.create_element(type, props = nil, children = nil, &block)
|
|
242
|
+
%x{
|
|
243
|
+
const operabu = self.render_buffer;
|
|
244
|
+
let component = null;
|
|
245
|
+
let native_props = null;
|
|
246
|
+
if (typeof type.react_component !== 'undefined') { component = type.react_component; }
|
|
247
|
+
else { component = type; }
|
|
248
|
+
if (block !== nil) {
|
|
249
|
+
operabu.push([]);
|
|
250
|
+
// console.log("create_element pushed", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
251
|
+
let block_result = block.$call();
|
|
252
|
+
if (block_result && block_result !== nil) { Opal.React.render_block_result(block_result); }
|
|
253
|
+
// console.log("create_element popping", Opal.React.render_buffer, Opal.React.render_buffer.toString());
|
|
254
|
+
children = operabu.pop();
|
|
255
|
+
} else if (children === nil) { children = []; }
|
|
256
|
+
else if (typeof children === 'string') { children = [children]; }
|
|
257
|
+
if (props && props !== nil) { native_props = self.to_native_react_props(props); }
|
|
258
|
+
return Opal.global.React.createElement.apply(this, [component, native_props].concat(children));
|
|
259
|
+
}
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def self.create_factory(type)
|
|
263
|
+
native_function = `Opal.global.React.createFactory(type)`
|
|
264
|
+
proc { `native_function.call()` }
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def self.create_ref
|
|
268
|
+
React::Ref.new(`Opal.global.React.createRef()`)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def self.forwardRef(&block)
|
|
272
|
+
# TODO whats the return here? A React:Element?, doc says a React node, whats that?
|
|
273
|
+
`Opal.global.React.forwardRef( function(props, ref) { return block.$call().$to_n(); })`
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def self.is_valid_element(react_element)
|
|
277
|
+
`Opal.global.React.isValidElement(react_element)`
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def self.lazy(import_statement_function)
|
|
281
|
+
`Opal.global.React.lazy(import_statement_function)`
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def self.memo(function_component, &block)
|
|
285
|
+
if block_given?
|
|
286
|
+
%x{
|
|
287
|
+
var fun = function(prev_props, next_props) {
|
|
288
|
+
return #{block.call(::React::Component::Props.new(`{props: prev_props}`), ::React::Component::Props.new(`{props: next_props}`))};
|
|
289
|
+
}
|
|
290
|
+
return Opal.global.React.memo(function_component, fun);
|
|
291
|
+
}
|
|
292
|
+
else
|
|
293
|
+
`Opal.global.React.memo(function_component)`
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|