isomorfeus-react 16.10.0 → 16.10.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.
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