isomorfeus-preact 10.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +62 -0
- data/lib/browser/delegate_native.rb +70 -0
- data/lib/browser/element.rb +176 -0
- data/lib/browser/element/canvas.rb +17 -0
- data/lib/browser/element/media.rb +78 -0
- data/lib/browser/event.rb +92 -0
- data/lib/browser/event_target.rb +39 -0
- data/lib/browser/file_list.rb +125 -0
- data/lib/browser/iterable.rb +15 -0
- data/lib/isomorfeus-preact.rb +109 -0
- data/lib/isomorfeus/preact/config.rb +189 -0
- data/lib/isomorfeus/preact/memcached_component_cache.rb +19 -0
- data/lib/isomorfeus/preact/redis_component_cache.rb +19 -0
- data/lib/isomorfeus/preact/thread_local_component_cache.rb +17 -0
- data/lib/isomorfeus/preact_view_helper.rb +188 -0
- data/lib/isomorfeus/props/validate_hash_proxy.rb +186 -0
- data/lib/isomorfeus/props/validator.rb +159 -0
- data/lib/isomorfeus/top_level.rb +101 -0
- data/lib/isomorfeus/top_level_ssr.rb +27 -0
- data/lib/isomorfeus_preact/lucid_app/api.rb +22 -0
- data/lib/isomorfeus_preact/lucid_app/base.rb +7 -0
- data/lib/isomorfeus_preact/lucid_app/mixin.rb +16 -0
- data/lib/isomorfeus_preact/lucid_app/native_component_constructor.rb +91 -0
- data/lib/isomorfeus_preact/lucid_component/api.rb +68 -0
- data/lib/isomorfeus_preact/lucid_component/app_store_proxy.rb +37 -0
- data/lib/isomorfeus_preact/lucid_component/base.rb +7 -0
- data/lib/isomorfeus_preact/lucid_component/class_store_proxy.rb +44 -0
- data/lib/isomorfeus_preact/lucid_component/initializer.rb +14 -0
- data/lib/isomorfeus_preact/lucid_component/instance_store_proxy.rb +44 -0
- data/lib/isomorfeus_preact/lucid_component/mixin.rb +15 -0
- data/lib/isomorfeus_preact/lucid_component/native_component_constructor.rb +84 -0
- data/lib/isomorfeus_preact/lucid_component/styles_api.rb +31 -0
- data/lib/isomorfeus_preact/lucid_component/styles_wrapper.rb +40 -0
- data/lib/isomorfeus_preact/lucid_func/base.rb +7 -0
- data/lib/isomorfeus_preact/lucid_func/initializer.rb +11 -0
- data/lib/isomorfeus_preact/lucid_func/mixin.rb +12 -0
- data/lib/isomorfeus_preact/lucid_func/native_component_constructor.rb +55 -0
- data/lib/isomorfeus_preact/preact/function_component/api.rb +123 -0
- data/lib/isomorfeus_preact/preact/function_component/base.rb +9 -0
- data/lib/isomorfeus_preact/preact/function_component/initializer.rb +10 -0
- data/lib/isomorfeus_preact/preact/function_component/mixin.rb +12 -0
- data/lib/isomorfeus_preact/preact/function_component/native_component_constructor.rb +48 -0
- data/lib/lucid_app/context.rb +24 -0
- data/lib/lucid_prop_declaration/mixin.rb +126 -0
- data/lib/preact.rb +309 -0
- data/lib/preact/component/api.rb +124 -0
- data/lib/preact/component/base.rb +9 -0
- data/lib/preact/component/callbacks.rb +102 -0
- data/lib/preact/component/elements.rb +64 -0
- data/lib/preact/component/initializer.rb +11 -0
- data/lib/preact/component/mixin.rb +15 -0
- data/lib/preact/component/native_component_constructor.rb +65 -0
- data/lib/preact/component/params.rb +18 -0
- data/lib/preact/component/props.rb +55 -0
- data/lib/preact/component/resolution.rb +97 -0
- data/lib/preact/component/state.rb +58 -0
- data/lib/preact/context_wrapper.rb +46 -0
- data/lib/preact/native_constant_wrapper.rb +29 -0
- data/lib/preact/options.rb +98 -0
- data/lib/preact/ref.rb +17 -0
- data/lib/preact/version.rb +3 -0
- metadata +301 -0
@@ -0,0 +1,12 @@
|
|
1
|
+
module Preact
|
2
|
+
module FunctionComponent
|
3
|
+
module Mixin
|
4
|
+
def self.included(base)
|
5
|
+
base.include(::Preact::Component::Elements)
|
6
|
+
base.include(::Preact::FunctionComponent::Initializer)
|
7
|
+
base.include(::Preact::FunctionComponent::Api)
|
8
|
+
base.extend(::Preact::FunctionComponent::NativeComponentConstructor)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Preact
|
2
|
+
module FunctionComponent
|
3
|
+
module NativeComponentConstructor
|
4
|
+
def self.extended(base)
|
5
|
+
component_name = base.to_s
|
6
|
+
%x{
|
7
|
+
base.instance_init = function(initial) {
|
8
|
+
let ruby_state = { instance: #{base.new(`{}`)} };
|
9
|
+
ruby_state.instance.__ruby_instance = ruby_state.instance;
|
10
|
+
return ruby_state;
|
11
|
+
}
|
12
|
+
base.instance_reducer = function(state, action) { return state; }
|
13
|
+
base.preact_component = function(props) {
|
14
|
+
const oper = Opal.Preact;
|
15
|
+
oper.render_buffer.push([]);
|
16
|
+
// console.log("function pushed", oper.render_buffer, oper.render_buffer.toString());
|
17
|
+
const [__ruby_state, __ruby_dispatch] = Opal.global.PreactHooks.useReducer(base.instance_reducer, null, base.instance_init);
|
18
|
+
const __ruby_instance = __ruby_state.instance;
|
19
|
+
__ruby_instance.props = props;
|
20
|
+
oper.active_components.push(__ruby_instance);
|
21
|
+
let block_result = #{`__ruby_instance`.instance_exec(&`base.render_block`)};
|
22
|
+
if (block_result && block_result !== nil) { oper.render_block_result(block_result); }
|
23
|
+
oper.active_components.pop();
|
24
|
+
// console.log("function popping", oper.render_buffer, oper.render_buffer.toString());
|
25
|
+
let result = oper.render_buffer.pop();
|
26
|
+
return (result.length === 1) ? result[0] : result;
|
27
|
+
}
|
28
|
+
base.preact_component.displayName = #{component_name};
|
29
|
+
}
|
30
|
+
|
31
|
+
base_module = base.to_s.deconstantize
|
32
|
+
if base_module != ''
|
33
|
+
base_module.constantize.define_singleton_method(base.to_s.demodulize) do |*args, &block|
|
34
|
+
`Opal.Preact.internal_prepare_args_and_render(#{base}.preact_component, args, block)`
|
35
|
+
end
|
36
|
+
else
|
37
|
+
Object.define_method(base.to_s) do |*args, &block|
|
38
|
+
`Opal.Preact.internal_prepare_args_and_render(#{base}.preact_component, args, block)`
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def render(&block)
|
43
|
+
`base.render_block = #{block}`
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module LucidApp
|
2
|
+
module Context
|
3
|
+
def self.create_application_context
|
4
|
+
nano_css = `null`
|
5
|
+
css_server = `null`
|
6
|
+
css_server = `document.getElementById('css-server-side')` unless on_ssr?
|
7
|
+
%x{
|
8
|
+
let og = Opal.global;
|
9
|
+
nano_css = (css_server) ? og.NanoCSS.create({ sh: css_server }) : og.NanoCSS.create();
|
10
|
+
og.NanoCSSAddOns.rule(nano_css);
|
11
|
+
og.NanoCSSAddOns.sheet(nano_css);
|
12
|
+
og.NanoCSSAddOns.nesting(nano_css);
|
13
|
+
og.NanoCSSAddOns.hydrate(nano_css);
|
14
|
+
og.NanoCSSAddOns.unitless(nano_css);
|
15
|
+
og.NanoCSSAddOns.global(nano_css);
|
16
|
+
og.NanoCSSAddOns.keyframes(nano_css);
|
17
|
+
og.NanoCSSAddOns.fade_in(nano_css);
|
18
|
+
og.NanoCSSAddOns.fade_out(nano_css);
|
19
|
+
og.NanoCSSInstance = nano_css;
|
20
|
+
}
|
21
|
+
Preact.create_context('LucidApplicationContext', { iso_store: Isomorfeus.store, nano_css: nano_css })
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module LucidPropDeclaration
|
2
|
+
module Mixin
|
3
|
+
if RUBY_ENGINE == 'opal'
|
4
|
+
def self.extended(base)
|
5
|
+
def prop(prop_name, validate_hash = { required: true })
|
6
|
+
validate_hash = validate_hash.to_h if validate_hash.class == Isomorfeus::Props::ValidateHashProxy
|
7
|
+
if validate_hash.key?(:default)
|
8
|
+
%x{
|
9
|
+
if (base.lucid_preact_component) {
|
10
|
+
let preact_prop_name = Opal.Preact.lower_camelize(prop_name);
|
11
|
+
#{value = validate_hash[:default]}
|
12
|
+
if (!base.lucid_preact_component.defaultProps) { base.lucid_preact_component.defaultProps = {}; }
|
13
|
+
base.lucid_preact_component.defaultProps[preact_prop_name] = value;
|
14
|
+
if (!base.lucid_preact_component.propTypes) { base.lucid_preact_component.propTypes = {}; }
|
15
|
+
base.lucid_preact_component.propTypes[preact_prop_name] = base.lucid_preact_component.prototype.validateProp;
|
16
|
+
} else if (base.preact_component) {
|
17
|
+
let preact_prop_name = Opal.Preact.lower_camelize(prop_name);
|
18
|
+
#{value = validate_hash[:default]}
|
19
|
+
if (!base.preact_component.defaultProps) { base.preact_component.defaultProps = {}; }
|
20
|
+
base.preact_component.defaultProps[preact_prop_name] = value;
|
21
|
+
if (!base.preact_component.propTypes) { base.preact_component.propTypes = {}; }
|
22
|
+
base.preact_component.propTypes[preact_prop_name] = base.preact_component.prototype.validateProp;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
declared_props[prop_name.to_sym] = validate_hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate_function
|
31
|
+
%x{
|
32
|
+
if (typeof self.validate_function === 'undefined') {
|
33
|
+
self.validate_function = function(props_object) {
|
34
|
+
try { self.$validate_props(Opal.Hash.$new(props_object)) }
|
35
|
+
catch (e) { return e.message; }
|
36
|
+
}
|
37
|
+
}
|
38
|
+
return self.validate_function;
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_prop_function(prop)
|
43
|
+
function_name = "validate_#{prop}_function"
|
44
|
+
%x{
|
45
|
+
if (typeof self[function_name] === 'undefined') {
|
46
|
+
self[function_name] = function(value) {
|
47
|
+
try { self.$validate_prop(prop, value); }
|
48
|
+
catch (e) { return e.message; }
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return self[function_name];
|
52
|
+
}
|
53
|
+
end
|
54
|
+
else
|
55
|
+
def prop(prop_name, validate_hash = { required: true })
|
56
|
+
validate_hash = validate_hash.to_h if validate_hash.class == Isomorfeus::Props::ValidateHashProxy
|
57
|
+
declared_props[prop_name.to_sym] = validate_hash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def declared_props
|
62
|
+
@declared_props ||= {}
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid_prop?(prop, value)
|
66
|
+
validate_prop(prop, value)
|
67
|
+
rescue
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
def valid_props?(props)
|
72
|
+
validate_props(props)
|
73
|
+
rescue
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate
|
78
|
+
Isomorfeus::Props::ValidateHashProxy.new
|
79
|
+
end
|
80
|
+
|
81
|
+
def validate_prop(prop, value)
|
82
|
+
return false unless declared_props.key?(prop)
|
83
|
+
validator = Isomorfeus::Props::Validator.new(self, prop, value, declared_props[prop])
|
84
|
+
validator.validate!
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
def validate_props(props)
|
89
|
+
props = {} unless props
|
90
|
+
declared_props.each_key do |prop|
|
91
|
+
if declared_props[prop].key?(:required) && declared_props[prop][:required] && !props.key?(prop)
|
92
|
+
Isomorfeus.raise_error(message: "Required prop #{prop} not given!")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
result = true
|
96
|
+
props.each do |p, v|
|
97
|
+
r = validate_prop(p, v)
|
98
|
+
result = false unless r
|
99
|
+
end
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
def validated_prop(prop, value)
|
104
|
+
Isomorfeus.raise_error(message: "No such prop #{prop} declared!") unless declared_props.key?(prop)
|
105
|
+
validator = Isomorfeus::Props::Validator.new(self, prop, value, declared_props[prop])
|
106
|
+
validator.validated_value
|
107
|
+
end
|
108
|
+
|
109
|
+
def validated_props(props)
|
110
|
+
props = {} unless props
|
111
|
+
|
112
|
+
declared_props.each_key do |prop|
|
113
|
+
if declared_props[prop].key?(:required) && declared_props[prop][:required] && !props.key?(prop)
|
114
|
+
Isomorfeus.raise_error(message: "Required prop #{prop} not given!")
|
115
|
+
end
|
116
|
+
props[prop] = nil unless props.key?(prop) # let validator handle value
|
117
|
+
end
|
118
|
+
|
119
|
+
result = {}
|
120
|
+
props.each do |p, v|
|
121
|
+
result[p] = validated_prop(p, v)
|
122
|
+
end
|
123
|
+
result
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/preact.rb
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
module Preact
|
2
|
+
%x{
|
3
|
+
self.render_buffer = [];
|
4
|
+
|
5
|
+
self.set_validate_prop = function(component, prop_name) {
|
6
|
+
let core = component.preact_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 #{::Browser::Event.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
|
+
self.prop_dictionary = {};
|
118
|
+
|
119
|
+
self.to_native_preact_props = function(ruby_style_props) {
|
120
|
+
let result = {};
|
121
|
+
let keys = ruby_style_props.$$keys;
|
122
|
+
let keys_length = keys.length;
|
123
|
+
let key = '';
|
124
|
+
for (let i = 0; i < keys_length; i++) {
|
125
|
+
key = keys[i];
|
126
|
+
let value = ruby_style_props.$$smap[key];
|
127
|
+
if (key[0] === 'o' && key[1] === 'n' && key[2] === '_') {
|
128
|
+
let type = typeof value;
|
129
|
+
if (type === "function") {
|
130
|
+
let active_c = self.active_component();
|
131
|
+
result[self.lower_camelize(key)] = function(event, info) {
|
132
|
+
let ruby_event = self.native_to_ruby_event(event);
|
133
|
+
#{`active_c.__ruby_instance`.instance_exec(`ruby_event`, `info`, &`value`)};
|
134
|
+
}
|
135
|
+
} else if (type === "object" && typeof value.m === "object" && typeof value.m.$call === "function" ) {
|
136
|
+
if (!value.preact_event_handler_function) {
|
137
|
+
value.preact_event_handler_function = function(event, info) {
|
138
|
+
let ruby_event = self.native_to_ruby_event(event);
|
139
|
+
if (value.a.length > 0) { value.m.$call.apply(value.m, [ruby_event, info].concat(value.a)); }
|
140
|
+
else { value.m.$call(ruby_event, info); }
|
141
|
+
};
|
142
|
+
}
|
143
|
+
result[self.lower_camelize(key)] = value.preact_event_handler_function;
|
144
|
+
} else if (type === "string" ) {
|
145
|
+
let active_component = self.active_component();
|
146
|
+
let method_ref;
|
147
|
+
let method_name = '$' + value;
|
148
|
+
if (typeof active_component[method_name] === "function") {
|
149
|
+
// got a ruby instance
|
150
|
+
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
|
151
|
+
else if (active_component.method_refs && active_component.method_refs[value]) { method_ref = active_component.method_refs[value]; } // ruby function component
|
152
|
+
else { method_ref = active_component.$method_ref(value); } // create the ref
|
153
|
+
} else if (typeof active_component.__ruby_instance[method_name] === "function") {
|
154
|
+
// got a native instance
|
155
|
+
if (active_component.method_refs && active_component.method_refs[value]) { method_ref = active_component.method_refs[value]; }
|
156
|
+
else { method_ref = active_component.__ruby_instance.$method_ref(value); } // create ref for native
|
157
|
+
}
|
158
|
+
if (method_ref) {
|
159
|
+
if (!method_ref.preact_event_handler_function) {
|
160
|
+
method_ref.preact_event_handler_function = function(event, info) {
|
161
|
+
let ruby_event = self.native_to_ruby_event(event);
|
162
|
+
method_ref.m.$call(ruby_event, info)
|
163
|
+
};
|
164
|
+
}
|
165
|
+
result[self.lower_camelize(key)] = method_ref.preact_event_handler_function;
|
166
|
+
} else {
|
167
|
+
let component_name;
|
168
|
+
if (active_component.__ruby_instance) { component_name = active_component.__ruby_instance.$to_s(); }
|
169
|
+
else { component_name = active_component.$to_s(); }
|
170
|
+
#{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`}")}
|
171
|
+
}
|
172
|
+
} else {
|
173
|
+
let active_component = self.active_component();
|
174
|
+
let component_name;
|
175
|
+
if (active_component.__ruby_instance) { component_name = active_component.__ruby_instance.$to_s(); }
|
176
|
+
else { component_name = active_component.$to_s(); }
|
177
|
+
#{Isomorfeus.raise_error(message: "Received invalid value for #{`key`} with #{`value`} within component: #{`component_name`}")}
|
178
|
+
console.error( + key + " event handler:", value, " within component:", self.active_component());
|
179
|
+
}
|
180
|
+
} else if (key[0] === 'a' && key.startsWith("aria_")) {
|
181
|
+
result[key.replace("_", "-")] = value;
|
182
|
+
} else if (key === "style" || key === "theme") {
|
183
|
+
if (typeof value.$to_n === "function") { value = value.$to_n() }
|
184
|
+
result[key] = value;
|
185
|
+
} else {
|
186
|
+
result[self.lower_camelize(key)] = value;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
return result;
|
190
|
+
};
|
191
|
+
|
192
|
+
self.render_block_result = function(block_result) {
|
193
|
+
if (block_result.constructor === String || block_result.constructor === Number) {
|
194
|
+
Opal.Preact.render_buffer[Opal.Preact.render_buffer.length - 1].push(block_result);
|
195
|
+
}
|
196
|
+
};
|
197
|
+
|
198
|
+
self.internal_render = function(component, props, string_child, block) {
|
199
|
+
const operabu = self.render_buffer;
|
200
|
+
let native_props;
|
201
|
+
if (props && props !== nil) { native_props = self.to_native_preact_props(props); }
|
202
|
+
if (string_child) {
|
203
|
+
operabu[operabu.length - 1].push(Opal.global.Preact.createElement(component, native_props, string_child));
|
204
|
+
} else if (block && block !== nil) {
|
205
|
+
operabu.push([]);
|
206
|
+
// console.log("internal_render pushed", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
|
207
|
+
let block_result = block.$call();
|
208
|
+
if (block_result && block_result !== nil) { Opal.Preact.render_block_result(block_result); }
|
209
|
+
// console.log("internal_render popping", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
|
210
|
+
let children = operabu.pop();
|
211
|
+
operabu[operabu.length - 1].push(Opal.global.Preact.createElement.apply(this, [component, native_props].concat(children)));
|
212
|
+
} else {
|
213
|
+
operabu[operabu.length - 1].push(Opal.global.Preact.createElement(component, native_props));
|
214
|
+
}
|
215
|
+
};
|
216
|
+
}
|
217
|
+
|
218
|
+
|
219
|
+
def self.create_element(type, props = nil, children = nil, &block)
|
220
|
+
%x{
|
221
|
+
const operabu = self.render_buffer;
|
222
|
+
let component = null;
|
223
|
+
let native_props = null;
|
224
|
+
if (typeof type.preact_component !== 'undefined') { component = type.preact_component; }
|
225
|
+
else { component = type; }
|
226
|
+
if (block !== nil) {
|
227
|
+
operabu.push([]);
|
228
|
+
// console.log("create_element pushed", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
|
229
|
+
let block_result = block.$call();
|
230
|
+
if (block_result && block_result !== nil) { Opal.Preact.render_block_result(block_result); }
|
231
|
+
// console.log("create_element popping", Opal.Preact.render_buffer, Opal.Preact.render_buffer.toString());
|
232
|
+
children = operabu.pop();
|
233
|
+
} else if (children === nil) { children = []; }
|
234
|
+
else if (typeof children === 'string') { children = [children]; }
|
235
|
+
if (props && props !== nil) { native_props = self.to_native_preact_props(props); }
|
236
|
+
return Opal.global.Preact.createElement.apply(this, [component, native_props].concat(children));
|
237
|
+
}
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.to_child_array(props_children)
|
241
|
+
`Opal.global.Preact.toChildArray(children)`
|
242
|
+
end
|
243
|
+
|
244
|
+
def self.clone_element(ruby_preact_element, props = nil, children = nil, &block)
|
245
|
+
block_result = `null`
|
246
|
+
if block_given?
|
247
|
+
block_result = block.call
|
248
|
+
block_result = `null` unless block_result
|
249
|
+
end
|
250
|
+
native_props = props ? `Opal.Preact.to_native_preact_props(props)` : `null`
|
251
|
+
`Opal.global.Preact.cloneElement(ruby_preact_element.$to_n(), native_props, block_result)`
|
252
|
+
end
|
253
|
+
|
254
|
+
def self.create_context(const_name, default_value)
|
255
|
+
%x{
|
256
|
+
Opal.global[const_name] = Opal.global.Preact.createContext(default_value);
|
257
|
+
var new_const = #{Preact::ContextWrapper.new(`Opal.global[const_name]`)};
|
258
|
+
#{Object.const_set(const_name, `new_const`)};
|
259
|
+
return new_const;
|
260
|
+
}
|
261
|
+
end
|
262
|
+
|
263
|
+
def self.create_ref
|
264
|
+
Preact::Ref.new(`Opal.global.Preact.createRef()`)
|
265
|
+
end
|
266
|
+
|
267
|
+
def self.hydrate(native_preact_element, container_node, replace_node, &block)
|
268
|
+
# container is a native DOM element
|
269
|
+
if block_given?
|
270
|
+
`Opal.global.Preact.hydrate(native_preact_element, container_node, function() { block.$call() })`
|
271
|
+
else
|
272
|
+
`Opal.global.Preact.hydrate(native_preact_element, container_node)`
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def self.location_hook(location)
|
277
|
+
%x{
|
278
|
+
if (Opal.global.locationHook) { return Opal.global.locationHook; }
|
279
|
+
else if (Opal.global.staticLocationHook) { return Opal.global.staticLocationHook(location); }
|
280
|
+
else { #{raise "Wouter Location Hooks not imported!"}; }
|
281
|
+
}
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.render(native_preact_element, container_node, replace_node)
|
285
|
+
# container is a native DOM element
|
286
|
+
if block_given?
|
287
|
+
`Opal.global.Preact.render(native_preact_element, container_node, function() { block.$call() })`
|
288
|
+
else
|
289
|
+
`Opal.global.Preact.render(native_preact_element, container_node)`
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
if on_ssr?
|
294
|
+
def self.render_to_string(native_preact_element)
|
295
|
+
`Opal.global.Preact.renderToString(native_preact_element)`
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def self.unmount_component_at_node(element_or_query)
|
300
|
+
if `(typeof element_or_query === 'string')` || (`(typeof element_or_query.$class === 'function')` && element_or_query.class == String)
|
301
|
+
element = `document.body.querySelector(element_or_query)`
|
302
|
+
elsif `(typeof element_or_query.$is_a === 'function')` && element_or_query.is_a?(Browser::Element)
|
303
|
+
element = element_or_query.to_n
|
304
|
+
else
|
305
|
+
element = element_or_query
|
306
|
+
end
|
307
|
+
`Opal.global.Preact.render(null, element)`
|
308
|
+
end
|
309
|
+
end
|