isomorfeus-react 16.10.0 → 16.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +64 -0
  3. data/lib/browser/delegate_native.rb +70 -0
  4. data/lib/browser/element.rb +176 -0
  5. data/lib/browser/element/canvas.rb +17 -0
  6. data/lib/browser/element/media.rb +78 -0
  7. data/lib/browser/event.rb +92 -0
  8. data/lib/browser/event_target.rb +39 -0
  9. data/lib/browser/file_list.rb +125 -0
  10. data/lib/browser/iterable.rb +15 -0
  11. data/lib/isomorfeus-react-material-ui.rb +10 -0
  12. data/lib/isomorfeus-react.rb +145 -0
  13. data/lib/isomorfeus/config.rb +130 -0
  14. data/lib/isomorfeus/props/validate_hash_proxy.rb +178 -0
  15. data/lib/isomorfeus/props/validator.rb +131 -0
  16. data/lib/isomorfeus/react_view_helper.rb +130 -0
  17. data/lib/isomorfeus/top_level.rb +86 -0
  18. data/lib/isomorfeus/top_level_ssr.rb +28 -0
  19. data/lib/lucid_app/api.rb +30 -0
  20. data/lib/lucid_app/base.rb +7 -0
  21. data/lib/lucid_app/context.rb +7 -0
  22. data/lib/lucid_app/mixin.rb +20 -0
  23. data/lib/lucid_app/native_component_constructor.rb +105 -0
  24. data/lib/lucid_component/app_store_defaults.rb +36 -0
  25. data/lib/lucid_component/app_store_proxy.rb +38 -0
  26. data/lib/lucid_component/base.rb +7 -0
  27. data/lib/lucid_component/class_store_proxy.rb +41 -0
  28. data/lib/lucid_component/component_class_store_defaults.rb +38 -0
  29. data/lib/lucid_component/component_instance_store_defaults.rb +35 -0
  30. data/lib/lucid_component/event_handler.rb +17 -0
  31. data/lib/lucid_component/initializer.rb +12 -0
  32. data/lib/lucid_component/instance_store_proxy.rb +45 -0
  33. data/lib/lucid_component/mixin.rb +18 -0
  34. data/lib/lucid_component/native_component_constructor.rb +116 -0
  35. data/lib/lucid_component/reducers.rb +48 -0
  36. data/lib/lucid_component/store_api.rb +38 -0
  37. data/lib/lucid_component/styles_support.rb +37 -0
  38. data/lib/lucid_material/app/base.rb +9 -0
  39. data/lib/lucid_material/app/mixin.rb +22 -0
  40. data/lib/lucid_material/app/native_component_constructor.rb +107 -0
  41. data/lib/lucid_material/component/base.rb +9 -0
  42. data/lib/lucid_material/component/mixin.rb +20 -0
  43. data/lib/lucid_material/component/native_component_constructor.rb +118 -0
  44. data/lib/lucid_prop_declaration/mixin.rb +91 -0
  45. data/lib/react.rb +195 -0
  46. data/lib/react/active_support_support.rb +13 -0
  47. data/lib/react/children.rb +35 -0
  48. data/lib/react/component/api.rb +80 -0
  49. data/lib/react/component/base.rb +9 -0
  50. data/lib/react/component/callbacks.rb +106 -0
  51. data/lib/react/component/elements.rb +60 -0
  52. data/lib/react/component/event_handler.rb +19 -0
  53. data/lib/react/component/features.rb +47 -0
  54. data/lib/react/component/history.rb +36 -0
  55. data/lib/react/component/initializer.rb +11 -0
  56. data/lib/react/component/location.rb +15 -0
  57. data/lib/react/component/match.rb +31 -0
  58. data/lib/react/component/mixin.rb +19 -0
  59. data/lib/react/component/native_component_constructor.rb +93 -0
  60. data/lib/react/component/props.rb +59 -0
  61. data/lib/react/component/resolution.rb +70 -0
  62. data/lib/react/component/should_component_update.rb +14 -0
  63. data/lib/react/component/state.rb +52 -0
  64. data/lib/react/component/styles.rb +27 -0
  65. data/lib/react/component/unsafe_api.rb +33 -0
  66. data/lib/react/context_wrapper.rb +46 -0
  67. data/lib/react/function_component/api.rb +63 -0
  68. data/lib/react/function_component/base.rb +9 -0
  69. data/lib/react/function_component/creator.rb +32 -0
  70. data/lib/react/function_component/event_handler.rb +13 -0
  71. data/lib/react/function_component/mixin.rb +14 -0
  72. data/lib/react/function_component/resolution.rb +62 -0
  73. data/lib/react/memo_component/base.rb +9 -0
  74. data/lib/react/memo_component/creator.rb +32 -0
  75. data/lib/react/memo_component/mixin.rb +14 -0
  76. data/lib/react/native_constant_wrapper.rb +26 -0
  77. data/lib/react/pure_component/base.rb +9 -0
  78. data/lib/react/pure_component/mixin.rb +18 -0
  79. data/lib/react/ref.rb +13 -0
  80. data/lib/react/synthetic_event.rb +53 -0
  81. data/lib/react/version.rb +3 -0
  82. data/lib/react_dom.rb +47 -0
  83. data/lib/react_dom_server.rb +19 -0
  84. metadata +84 -2
@@ -0,0 +1,60 @@
1
+ module React
2
+ module Component
3
+ module Elements
4
+ # https://www.w3.org/TR/html52/fullindex.html#index-elements
5
+ # https://www.w3.org/TR/SVG11/eltindex.html
6
+ SUPPORTED_HTML_AND_SVG_ELEMENTS = %w[
7
+ a abbr address area article aside audio
8
+ b base bdi bdo blockquote body br button
9
+ canvas caption cite code col colgroup
10
+ data datalist dd del details dfn dialog div dl dt
11
+ em embed
12
+ fieldset figcaption figure footer form
13
+ h1 h2 h3 h4 h5 h6 head header hr html
14
+ i iframe img input ins
15
+ kbd
16
+ label legend li link
17
+ main map mark meta meter
18
+ nav noscript
19
+ object ol optgroup option output
20
+ p param picture pre progress
21
+ q
22
+ rp rt rtc ruby
23
+ s samp script section select small source span strong style sub summary sup
24
+ table tbody td template textarea tfoot th thead time title tr track
25
+ u ul
26
+ var video
27
+ wbr
28
+ altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion animateTransform
29
+ circle clipPath color-profile cursor
30
+ defs desc
31
+ ellipse
32
+ feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting
33
+ feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur
34
+ feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting
35
+ feSpotLight feTile feTurbulence
36
+ filter font font-face font-face-format font-face-name font-face-src font-face-uri foreignObject
37
+ g glyph glyphRef
38
+ hkern
39
+ image
40
+ line linearGradient
41
+ marker mask metadata missing-glyph mpath
42
+ path pattern polygon polyline
43
+ radialGradient rect
44
+ script set stop style svg switch symbol
45
+ text textPath tref tspan
46
+ use
47
+ view vkern
48
+ ]
49
+
50
+ SUPPORTED_HTML_AND_SVG_ELEMENTS.each do |element|
51
+ define_method(element) do |*args, &block|
52
+ `Opal.React.internal_prepare_args_and_render(element, args, block)`
53
+ end
54
+ define_method(`element.toUpperCase()`) do |*args, &block|
55
+ `Opal.React.internal_prepare_args_and_render(element, args, block)`
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,19 @@
1
+ module React
2
+ module Component
3
+ module EventHandler
4
+ def event_handlers
5
+ @event_handlers ||= []
6
+ end
7
+
8
+ def event_handler(name, &block)
9
+ event_handlers << name
10
+ %x{
11
+ self.react_component.prototype[name] = function(event, info) {
12
+ #{ruby_event = ::React::SyntheticEvent.new(`event`)};
13
+ #{`this.__ruby_instance`.instance_exec(ruby_event, `info`, &block)};
14
+ }
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,47 @@
1
+ module React
2
+ module Component
3
+ module Features
4
+ def Fragment(*args, &block)
5
+ `Opal.React.internal_prepare_args_and_render(Opal.global.React.Fragment, args, block)`
6
+ end
7
+
8
+ def Portal(element_or_query, &block)
9
+ if `(typeof element_or_query === 'string')` || (`(typeof element_or_query.$class === 'function')` && element_or_query.class == String)
10
+ element = `document.body.querySelector(element_or_query)`
11
+ elsif `(typeof element_or_query.$is_a === 'function')` && element_or_query.is_a?(Browser::Element)
12
+ element = element_or_query.to_n
13
+ else
14
+ element = element_or_query
15
+ end
16
+ %x{
17
+ Opal.React.render_buffer.push([]);
18
+ if (block !== nil) {
19
+ let block_result = block.$call()
20
+ let last_buffer_length = Opal.React.render_buffer[Opal.React.render_buffer.length - 1].length;
21
+ let last_buffer_element = Opal.React.render_buffer[Opal.React.render_buffer.length - 1][last_buffer_length - 1];
22
+ if (block_result && block_result !== last_buffer_element && (block_result !== nil && (typeof block_result === "string" || typeof block_result.$$typeof === "symbol" ||
23
+ (typeof block_result.constructor !== "undefined" && block_result.constructor === Array && block_result[0] && typeof block_result[0].$$typeof === "symbol")
24
+ ))) {
25
+ Opal.React.render_buffer[Opal.React.render_buffer.length - 1].push(block_result);
26
+ }
27
+ }
28
+ var react_element = Opal.global.React.createPortal(Opal.React.render_buffer.pop(), element);
29
+ Opal.React.render_buffer[Opal.React.render_buffer.length - 1].push(react_element);
30
+ return react_element;
31
+ }
32
+ end
33
+
34
+ def Profiler(*args, &block)
35
+ `Opal.React.internal_prepare_args_and_render(Opal.global.React.Profiler, args, block)`
36
+ end
37
+
38
+ def StrictMode(*args, &block)
39
+ `Opal.React.internal_prepare_args_and_render(Opal.global.React.StrictMode, args, block)`
40
+ end
41
+
42
+ def Suspense(*args, &block)
43
+ `Opal.React.internal_prepare_args_and_render(Opal.global.React.Suspense, args, block)`
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,36 @@
1
+ module React
2
+ module Component
3
+ class History
4
+ include ::Native::Wrapper
5
+
6
+ alias_native :block, :block
7
+ alias_native :create_href, :createHref
8
+ alias_native :go, :go
9
+ alias_native :go_back, :goBack
10
+ alias_native :go_forward, :goForward
11
+ alias_native :listen, :listen
12
+ alias_native :push, :push
13
+ alias_native :replace, :replace
14
+
15
+ alias _react_component_hitory_original_method_missing method_missing
16
+
17
+ def method_missing(prop, *args, &block)
18
+ @native.JS[:params].JS[prop]
19
+ end
20
+
21
+ def location
22
+ return @location if @location
23
+ return nil unless @native.JS[:props].JS[:location]
24
+ if @native.JS[:props].JS[:location].JS[:pathname]
25
+ @location = React::Component::Location.new(@native.JS[:props].JS[:location])
26
+ else
27
+ @native.JS[:props].JS[:location]
28
+ end
29
+ end
30
+
31
+ def to_n
32
+ @native
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,11 @@
1
+ module React
2
+ module Component
3
+ module Initializer
4
+ def initialize(native_component)
5
+ @native = native_component
6
+ @props = `Opal.React.Component.Props.$new(#@native)`
7
+ @state = `Opal.React.Component.State.$new(#@native)`
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module React
2
+ module Component
3
+ class Location
4
+ include ::Native::Wrapper
5
+
6
+ def method_missing(prop, *args, &block)
7
+ @native.JS[:params].JS[prop]
8
+ end
9
+
10
+ def to_n
11
+ @native
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ module React
2
+ module Component
3
+ class Match
4
+ include ::Native::Wrapper
5
+
6
+ def method_missing(prop, *args, &block)
7
+ @native.JS[:params].JS[prop]
8
+ end
9
+
10
+ def is_exact
11
+ @native.JS[:isExact]
12
+ end
13
+
14
+ def params
15
+ self
16
+ end
17
+
18
+ def path
19
+ @native.JS[:path]
20
+ end
21
+
22
+ def url
23
+ @native.JS[:url]
24
+ end
25
+
26
+ def to_n
27
+ @native
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module React
2
+ module Component
3
+ module Mixin
4
+ def self.included(base)
5
+ base.include(::Native::Wrapper)
6
+ base.extend(::React::Component::NativeComponentConstructor)
7
+ base.extend(::LucidPropDeclaration::Mixin)
8
+ base.extend(::React::Component::ShouldComponentUpdate)
9
+ base.extend(::React::Component::EventHandler)
10
+ base.include(::React::Component::Elements)
11
+ base.include(::React::Component::API)
12
+ base.include(::React::Component::Callbacks)
13
+ base.include(::React::Component::Initializer)
14
+ base.include(::React::Component::Features)
15
+ base.include(::React::Component::Resolution)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,93 @@
1
+ module React
2
+ module Component
3
+ module NativeComponentConstructor
4
+ # for should_component_update we apply ruby semantics for comparing props
5
+ # to do so, we convert the props to ruby hashes and then compare
6
+ # this makes sure, that for example rubys Nil object gets handled properly
7
+ def self.extended(base)
8
+ component_name = base.to_s
9
+ # language=JS
10
+ %x{
11
+ base.react_component = class extends Opal.global.React.Component {
12
+ constructor(props) {
13
+ super(props);
14
+ if (base.$default_state_defined()) {
15
+ this.state = base.$state().$to_n();
16
+ } else {
17
+ this.state = {};
18
+ };
19
+ this.__ruby_instance = base.$new(this);
20
+ var event_handlers = #{base.event_handlers};
21
+ for (var i = 0; i < event_handlers.length; i++) {
22
+ this[event_handlers[i]] = this[event_handlers[i]].bind(this);
23
+ }
24
+ var defined_refs = #{base.defined_refs};
25
+ for (var ref in defined_refs) {
26
+ if (defined_refs[ref] != null) {
27
+ this[ref] = function(element) {
28
+ element = Opal.React.native_element_or_component_to_ruby(element);
29
+ #{`this.__ruby_instance`.instance_exec(`element`, &`defined_refs[ref]`)}
30
+ }
31
+ this[ref] = this[ref].bind(this);
32
+ } else {
33
+ this[ref] = Opal.global.React.createRef();
34
+ }
35
+ }
36
+ }
37
+ static get displayName() {
38
+ return #{component_name};
39
+ }
40
+ render() {
41
+ Opal.React.render_buffer.push([]);
42
+ Opal.React.active_components.push(this);
43
+ #{`this.__ruby_instance`.instance_exec(&`base.render_block`)};
44
+ Opal.React.active_components.pop();
45
+ return Opal.React.render_buffer.pop();
46
+ }
47
+ shouldComponentUpdate(next_props, next_state) {
48
+ if (base.has_custom_should_component_update) {
49
+ return this.__ruby_instance["$should_component_update"](#{(Hash.new(next_props))}, #{Hash.new(next_state)});
50
+ } else {
51
+ var next_props_keys = Object.keys(next_props);
52
+ var this_props_keys = Object.keys(this.props);
53
+ if (next_props_keys.length !== this_props_keys.length) { return true; }
54
+
55
+ var next_state_keys = Object.keys(next_state);
56
+ var this_state_keys = Object.keys(this.state);
57
+ if (next_state_keys.length !== this_state_keys.length) { return true; }
58
+
59
+ for (var property in next_props) {
60
+ if (next_props.hasOwnProperty(property)) {
61
+ if (!this.props.hasOwnProperty(property)) { return true; };
62
+ if (property == "children") { if (next_props.children !== this.props.children) { return true; }}
63
+ else if (typeof next_props[property] !== "undefined" && next_props[property] !== null &&
64
+ typeof next_props[property]['$!='] !== "undefined" &&
65
+ typeof this.props[property] !== "undefined" && this.props[property] !== null &&
66
+ typeof this.props[property]['$!='] !== "undefined") {
67
+ if (#{ !! (`next_props[property]` != `this.props[property]`) }) { return true; };
68
+ } else if (next_props[property] !== this.props[property]) { return true; };
69
+ }
70
+ }
71
+ for (var property in next_state) {
72
+ if (next_state.hasOwnProperty(property)) {
73
+ if (!this.state.hasOwnProperty(property)) { return true; };
74
+ if (next_state[property] !== null && typeof next_state[property]['$!='] !== "undefined" &&
75
+ this.state[property] !== null && typeof this.state[property]['$!='] !== "undefined") {
76
+ if (#{ !! (`next_state[property]` != `this.state[property]`) }) { return true };
77
+ } else if (next_state[property] !== this.state[property]) { return true };
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+ }
83
+ validateProp(props, propName, componentName) {
84
+ try { base.$validate_prop(propName, props[propName]) }
85
+ catch (e) { return new Error(componentName + " Error: prop validation failed: " + e.message); }
86
+ return null;
87
+ }
88
+ }
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,59 @@
1
+ module React
2
+ module Component
3
+ class Props
4
+ include ::Native::Wrapper
5
+
6
+ def method_missing(prop, *args, &block)
7
+ %x{
8
+ var prop_name = Opal.React.lower_camelize(prop);
9
+ if (typeof #@native.props[prop_name] === 'undefined') { return #{nil}; }
10
+ return #@native.props[prop_name];
11
+ }
12
+ end
13
+
14
+ def classes
15
+ @classes ||= `Opal.React.Component.Styles.$new(#@native.props.classes)`
16
+ end
17
+
18
+ def theme
19
+ @theme ||= `Opal.React.Component.Styles.$new(#@native.props.theme)`
20
+ end
21
+
22
+ def isomorfeus_store
23
+ @native.JS[:props].JS[:isomorfeus_store]
24
+ end
25
+
26
+ # for router convenience
27
+ def history
28
+ return nil unless @native.JS[:props].JS[:history]
29
+ if @native.JS[:props].JS[:history].JS[:pathname]
30
+ React::Component::History.new(@native.JS[:props].JS[:history])
31
+ else
32
+ @native.JS[:props].JS[:history]
33
+ end
34
+ end
35
+
36
+ def location
37
+ return nil unless @native.JS[:props].JS[:location]
38
+ if @native.JS[:props].JS[:location].JS[:pathname]
39
+ React::Component::Location.new(@native.JS[:props].JS[:location])
40
+ else
41
+ @native.JS[:props].JS[:location]
42
+ end
43
+ end
44
+
45
+ def match
46
+ return nil unless @native.JS[:props].JS[:match]
47
+ if @native.JS[:props].JS[:match].JS[:path]
48
+ React::Component::Match.new(@native.JS[:props].JS[:match])
49
+ else
50
+ @native.JS[:props].JS[:match]
51
+ end
52
+ end
53
+
54
+ def to_n
55
+ @native.JS[:props]
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,70 @@
1
+ module React
2
+ module Component
3
+ module Resolution
4
+ def self.included(base)
5
+ base.instance_exec do
6
+ alias _react_component_resolution_original_const_missing const_missing
7
+
8
+ def const_missing(const_name)
9
+ # language=JS
10
+ %x{
11
+ if (typeof Opal.global[const_name] === "object") {
12
+ var new_const = #{React::NativeConstantWrapper.new(`Opal.global[const_name]`, const_name)};
13
+ #{Object.const_set(const_name, `new_const`)};
14
+ return new_const;
15
+ } else {
16
+ return #{_react_component_resolution_original_const_missing(const_name)};
17
+ }
18
+ }
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ alias _react_component_resolution_original_method_missing method_missing
25
+
26
+ def method_missing(component_name, *args, &block)
27
+ # html tags are defined as methods, so they will not end up here.
28
+ # first check for native component and render it, we want to be fast for native components
29
+ # second check for ruby component and render it, they are a bit slower anyway
30
+ # third pass on method missing
31
+ # language=JS
32
+ %x{
33
+ var component = null;
34
+ var component_type = typeof Opal.global[component_name];
35
+ if (component_type === "function" || component_type === "object") {
36
+ component = Opal.global[component_name];
37
+ } else {
38
+ var modules = self.$class().$to_s().split("::");
39
+ var modules_length = modules.length - 1;
40
+ var module;
41
+ var constant;
42
+ for (var i = modules_length; i > 0; i--) {
43
+ try {
44
+ module = modules.slice(0, i).join('::')
45
+ constant = self.$class().$const_get(module).$const_get(component_name, false);
46
+ if (typeof constant.react_component !== 'undefined') {
47
+ component = constant.react_component;
48
+ break;
49
+ }
50
+ } catch(err) { component = null; }
51
+ }
52
+ if (!component) {
53
+ try {
54
+ constant = Opal.Object.$const_get(component_name);
55
+ if (typeof constant.react_component !== 'undefined') {
56
+ component = constant.react_component;
57
+ }
58
+ } catch(err) { component = null; }
59
+ }
60
+ }
61
+ if (component) {
62
+ return Opal.React.internal_prepare_args_and_render(component, args, block);
63
+ } else {
64
+ return #{_react_component_resolution_original_method_missing(component_name, *args, block)};
65
+ }
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end