reactive-ruby 0.7.28 → 0.7.29
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +6 -0
- data/Gemfile.lock +4 -1
- data/README.md +132 -68
- data/Rakefile +5 -2
- data/example/examples/Gemfile +0 -2
- data/example/rails-tutorial/Gemfile +3 -2
- data/lib/generators/reactive_ruby/test_app/templates/application.rb +11 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/application.rb +2 -0
- data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +3 -0
- data/lib/generators/reactive_ruby/test_app/templates/boot.rb +6 -0
- data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
- data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
- data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +105 -0
- data/lib/rails-helpers/top_level_rails_component.rb +9 -16
- data/lib/{reactive-ruby → react}/api.rb +8 -65
- data/lib/{reactive-ruby → react}/callbacks.rb +0 -0
- data/lib/react/component.rb +266 -0
- data/lib/react/component/api.rb +48 -0
- data/lib/react/component/class_methods.rb +183 -0
- data/lib/{reactive-ruby → react}/element.rb +10 -11
- data/lib/{reactive-ruby → react}/event.rb +0 -0
- data/lib/{reactive-ruby → react}/ext/hash.rb +0 -0
- data/lib/{reactive-ruby → react}/ext/string.rb +0 -0
- data/lib/react/native_library.rb +57 -0
- data/lib/{reactive-ruby → react}/observable.rb +0 -4
- data/lib/{reactive-ruby → react}/rendering_context.rb +0 -6
- data/lib/{reactive-ruby → react}/state.rb +3 -6
- data/lib/{reactive-ruby → react}/top_level.rb +2 -3
- data/lib/react/validator.rb +127 -0
- data/lib/reactive-ruby.rb +20 -20
- data/lib/reactive-ruby/version.rb +1 -1
- data/{opal-spec/reactjs → spec}/index.html.erb +1 -1
- data/{opal-spec → spec/react}/callbacks_spec.rb +8 -9
- data/{opal-spec → spec/react}/component_spec.rb +170 -120
- data/spec/react/dsl_spec.rb +16 -0
- data/{opal-spec → spec/react}/element_spec.rb +7 -20
- data/{opal-spec → spec/react}/event_spec.rb +3 -1
- data/spec/react/native_library_spec.rb +10 -0
- data/spec/react/param_declaration_spec.rb +18 -0
- data/{opal-spec → spec/react}/react_spec.rb +3 -2
- data/spec/react/react_state_spec.rb +22 -0
- data/spec/react/top_level_component_spec.rb +68 -0
- data/{opal-spec → spec/react}/tutorial/tutorial_spec.rb +11 -13
- data/{opal-spec → spec/react}/validator_spec.rb +50 -4
- data/spec/reactive-ruby/isomorphic_helpers_spec.rb +22 -4
- data/spec/spec_helper.rb +51 -0
- data/spec/support/react/spec_helpers.rb +57 -0
- data/spec/vendor/es5-shim.min.js +6 -0
- metadata +56 -24
- data/lib/reactive-ruby/component.rb +0 -502
- data/lib/reactive-ruby/validator.rb +0 -99
- data/old-readme +0 -220
- data/opal-spec/spec_helper.rb +0 -29
@@ -0,0 +1,57 @@
|
|
1
|
+
module React
|
2
|
+
module SpecHelpers
|
3
|
+
`var ReactTestUtils = React.addons.TestUtils`
|
4
|
+
|
5
|
+
def renderToDocument(type, options = {})
|
6
|
+
element = React.create_element(type, options)
|
7
|
+
return renderElementToDocument(element)
|
8
|
+
end
|
9
|
+
|
10
|
+
def renderElementToDocument(element)
|
11
|
+
instance = Native(`ReactTestUtils.renderIntoDocument(#{element.to_n})`)
|
12
|
+
instance.class.include(React::Component::API)
|
13
|
+
return instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def simulateEvent(event, element, params = {})
|
17
|
+
simulator = Native(`ReactTestUtils.Simulate`)
|
18
|
+
simulator[event.to_s].call(`#{element.to_n}.getDOMNode()`, params)
|
19
|
+
end
|
20
|
+
|
21
|
+
def isElementOfType(element, type)
|
22
|
+
`React.addons.TestUtils.isElementOfType(#{element.to_n}, #{type.cached_component_class})`
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_element(type, options)
|
26
|
+
component = React.create_element(type, options)
|
27
|
+
element = `ReactTestUtils.renderIntoDocument(#{component.to_n})`
|
28
|
+
if `typeof React.findDOMNode === 'undefined'`
|
29
|
+
`$(element.getDOMNode())` # v0.12
|
30
|
+
else
|
31
|
+
`$(React.findDOMNode(element))` # v0.13
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def expect_component_to_eventually(component_class, opts = {}, &block)
|
36
|
+
# Calls block after each update of a component until it returns true.
|
37
|
+
# When it does set the expectation to true. Uses the after_update
|
38
|
+
# callback of the component_class, then instantiates an element of that
|
39
|
+
# class The call back is only called on updates, so the call back is
|
40
|
+
# manually called right after the element is created. Because React.rb
|
41
|
+
# runs the callback inside the components context, we have to setup a
|
42
|
+
# lambda to get back to correct context before executing run_async.
|
43
|
+
# Because run_async can only be run once it is protected by clearing
|
44
|
+
# element once the test passes.
|
45
|
+
element = nil
|
46
|
+
check_block = lambda do
|
47
|
+
context = block.arity > 0 ? self : element
|
48
|
+
run_async do
|
49
|
+
element = nil; expect(true).to be(true)
|
50
|
+
end if element and context.instance_exec(element, &block)
|
51
|
+
end
|
52
|
+
component_class.after_update { check_block.call }
|
53
|
+
element = build_element component_class, opts
|
54
|
+
check_block.call
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
/*!
|
2
|
+
* https://github.com/es-shims/es5-shim
|
3
|
+
* @license es5-shim Copyright 2009-2014 by contributors, MIT License
|
4
|
+
* see https://github.com/es-shims/es5-shim/blob/v4.1.0/LICENSE
|
5
|
+
*/
|
6
|
+
(function(t,e){"use strict";if(typeof define==="function"&&define.amd){define(e)}else if(typeof exports==="object"){module.exports=e()}else{t.returnExports=e()}})(this,function(){var t=Array.prototype;var e=Object.prototype;var r=Function.prototype;var n=String.prototype;var i=Number.prototype;var a=t.slice;var o=t.splice;var u=t.push;var l=t.unshift;var f=r.call;var s=e.toString;var c=Array.isArray||function ye(t){return s.call(t)==="[object Array]"};var p=typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol";var h;var v=Function.prototype.toString,g=function de(t){try{v.call(t);return true}catch(e){return false}},y="[object Function]",d="[object GeneratorFunction]";h=function me(t){if(typeof t!=="function"){return false}if(p){return g(t)}var e=s.call(t);return e===y||e===d};var m;var b=RegExp.prototype.exec,w=function be(t){try{b.call(t);return true}catch(e){return false}},T="[object RegExp]";m=function we(t){if(typeof t!=="object"){return false}return p?w(t):s.call(t)===T};var x;var O=String.prototype.valueOf,j=function Te(t){try{O.call(t);return true}catch(e){return false}},S="[object String]";x=function xe(t){if(typeof t==="string"){return true}if(typeof t!=="object"){return false}return p?j(t):s.call(t)===S};var E=function Oe(t){var e=s.call(t);var r=e==="[object Arguments]";if(!r){r=!c(t)&&t!==null&&typeof t==="object"&&typeof t.length==="number"&&t.length>=0&&h(t.callee)}return r};var N=function(t){var e=Object.defineProperty&&function(){try{Object.defineProperty({},"x",{});return true}catch(t){return false}}();var r;if(e){r=function(t,e,r,n){if(!n&&e in t){return}Object.defineProperty(t,e,{configurable:true,enumerable:false,writable:true,value:r})}}else{r=function(t,e,r,n){if(!n&&e in t){return}t[e]=r}}return function n(e,i,a){for(var o in i){if(t.call(i,o)){r(e,o,i[o],a)}}}}(e.hasOwnProperty);function I(t){var e=typeof t;return t===null||e==="undefined"||e==="boolean"||e==="number"||e==="string"}var D={ToInteger:function je(t){var e=+t;if(e!==e){e=0}else if(e!==0&&e!==1/0&&e!==-(1/0)){e=(e>0||-1)*Math.floor(Math.abs(e))}return e},ToPrimitive:function Se(t){var e,r,n;if(I(t)){return t}r=t.valueOf;if(h(r)){e=r.call(t);if(I(e)){return e}}n=t.toString;if(h(n)){e=n.call(t);if(I(e)){return e}}throw new TypeError},ToObject:function(t){if(t==null){throw new TypeError("can't convert "+t+" to object")}return Object(t)},ToUint32:function Ee(t){return t>>>0}};var M=function Ne(){};N(r,{bind:function Ie(t){var e=this;if(!h(e)){throw new TypeError("Function.prototype.bind called on incompatible "+e)}var r=a.call(arguments,1);var n;var i=function(){if(this instanceof n){var i=e.apply(this,r.concat(a.call(arguments)));if(Object(i)===i){return i}return this}else{return e.apply(t,r.concat(a.call(arguments)))}};var o=Math.max(0,e.length-r.length);var u=[];for(var l=0;l<o;l++){u.push("$"+l)}n=Function("binder","return function ("+u.join(",")+"){ return binder.apply(this, arguments); }")(i);if(e.prototype){M.prototype=e.prototype;n.prototype=new M;M.prototype=null}return n}});var F=f.bind(e.hasOwnProperty);var R=function(){var t=[1,2];var e=t.splice();return t.length===2&&c(e)&&e.length===0}();N(t,{splice:function De(t,e){if(arguments.length===0){return[]}else{return o.apply(this,arguments)}}},!R);var U=function(){var e={};t.splice.call(e,0,0,1);return e.length===1}();N(t,{splice:function Me(t,e){if(arguments.length===0){return[]}var r=arguments;this.length=Math.max(D.ToInteger(this.length),0);if(arguments.length>0&&typeof e!=="number"){r=a.call(arguments);if(r.length<2){r.push(this.length-t)}else{r[1]=D.ToInteger(e)}}return o.apply(this,r)}},!U);var k=[].unshift(0)!==1;N(t,{unshift:function(){l.apply(this,arguments);return this.length}},k);N(Array,{isArray:c});var A=Object("a");var C=A[0]!=="a"||!(0 in A);var P=function Fe(t){var e=true;var r=true;if(t){t.call("foo",function(t,r,n){if(typeof n!=="object"){e=false}});t.call([1],function(){"use strict";r=typeof this==="string"},"x")}return!!t&&e&&r};N(t,{forEach:function Re(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=arguments[1],i=-1,a=r.length>>>0;if(!h(t)){throw new TypeError}while(++i<a){if(i in r){t.call(n,r[i],i,e)}}}},!P(t.forEach));N(t,{map:function Ue(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=Array(n),a=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var o=0;o<n;o++){if(o in r){i[o]=t.call(a,r[o],o,e)}}return i}},!P(t.map));N(t,{filter:function ke(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=[],a,o=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var u=0;u<n;u++){if(u in r){a=r[u];if(t.call(o,a,u,e)){i.push(a)}}}return i}},!P(t.filter));N(t,{every:function Ae(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&!t.call(i,r[a],a,e)){return false}}return true}},!P(t.every));N(t,{some:function Ce(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0,i=arguments[1];if(!h(t)){throw new TypeError(t+" is not a function")}for(var a=0;a<n;a++){if(a in r&&t.call(i,r[a],a,e)){return true}}return false}},!P(t.some));var Z=false;if(t.reduce){Z=typeof t.reduce.call("es5",function(t,e,r,n){return n})==="object"}N(t,{reduce:function Pe(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0;if(!h(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduce of empty array with no initial value")}var i=0;var a;if(arguments.length>=2){a=arguments[1]}else{do{if(i in r){a=r[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i<n;i++){if(i in r){a=t.call(void 0,a,r[i],i,e)}}return a}},!Z);var J=false;if(t.reduceRight){J=typeof t.reduceRight.call("es5",function(t,e,r,n){return n})==="object"}N(t,{reduceRight:function Ze(t){var e=D.ToObject(this),r=C&&x(this)?this.split(""):e,n=r.length>>>0;if(!h(t)){throw new TypeError(t+" is not a function")}if(!n&&arguments.length===1){throw new TypeError("reduceRight of empty array with no initial value")}var i,a=n-1;if(arguments.length>=2){i=arguments[1]}else{do{if(a in r){i=r[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in r){i=t.call(void 0,i,r[a],a,e)}}while(a--);return i}},!J);var z=Array.prototype.indexOf&&[0,1].indexOf(1,2)!==-1;N(t,{indexOf:function Je(t){var e=C&&x(this)?this.split(""):D.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=0;if(arguments.length>1){n=D.ToInteger(arguments[1])}n=n>=0?n:Math.max(0,r+n);for(;n<r;n++){if(n in e&&e[n]===t){return n}}return-1}},z);var $=Array.prototype.lastIndexOf&&[0,1].lastIndexOf(0,-3)!==-1;N(t,{lastIndexOf:function ze(t){var e=C&&x(this)?this.split(""):D.ToObject(this),r=e.length>>>0;if(!r){return-1}var n=r-1;if(arguments.length>1){n=Math.min(n,D.ToInteger(arguments[1]))}n=n>=0?n:r-Math.abs(n);for(;n>=0;n--){if(n in e&&t===e[n]){return n}}return-1}},$);var B=!{toString:null}.propertyIsEnumerable("toString"),G=function(){}.propertyIsEnumerable("prototype"),H=!F("x","0"),L=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],X=L.length;N(Object,{keys:function $e(t){var e=h(t),r=E(t),n=t!==null&&typeof t==="object",i=n&&x(t);if(!n&&!e&&!r){throw new TypeError("Object.keys called on a non-object")}var a=[];var o=G&&e;if(i&&H||r){for(var u=0;u<t.length;++u){a.push(String(u))}}if(!r){for(var l in t){if(!(o&&l==="prototype")&&F(t,l)){a.push(String(l))}}}if(B){var f=t.constructor,s=f&&f.prototype===t;for(var c=0;c<X;c++){var p=L[c];if(!(s&&p==="constructor")&&F(t,p)){a.push(p)}}}return a}});var Y=Object.keys&&function(){return Object.keys(arguments).length===2}(1,2);var q=Object.keys;N(Object,{keys:function Be(e){if(E(e)){return q(t.slice.call(e))}else{return q(e)}}},!Y);var K=-621987552e5;var Q="-000001";var V=Date.prototype.toISOString&&new Date(K).toISOString().indexOf(Q)===-1;N(Date.prototype,{toISOString:function Ge(){var t,e,r,n,i;if(!isFinite(this)){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}n=this.getUTCFullYear();i=this.getUTCMonth();n+=Math.floor(i/12);i=(i%12+12)%12;t=[i+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];n=(n<0?"-":n>9999?"+":"")+("00000"+Math.abs(n)).slice(0<=n&&n<=9999?-4:-6);e=t.length;while(e--){r=t[e];if(r<10){t[e]="0"+r}}return n+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"}},V);var W=false;try{W=Date.prototype.toJSON&&new Date(NaN).toJSON()===null&&new Date(K).toJSON().indexOf(Q)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(_){}if(!W){Date.prototype.toJSON=function He(t){var e=Object(this),r=D.ToPrimitive(e),n;if(typeof r==="number"&&!isFinite(r)){return null}n=e.toISOString;if(typeof n!=="function"){throw new TypeError("toISOString property is not callable")}return n.call(e)}}var te=Date.parse("+033658-09-27T01:46:40.000Z")===1e15;var ee=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"));var re=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(!Date.parse||re||ee||!te){Date=function(t){function e(r,n,i,a,o,u,l){var f=arguments.length;if(this instanceof t){var s=f===1&&String(r)===r?new t(e.parse(r)):f>=7?new t(r,n,i,a,o,u,l):f>=6?new t(r,n,i,a,o,u):f>=5?new t(r,n,i,a,o):f>=4?new t(r,n,i,a):f>=3?new t(r,n,i):f>=2?new t(r,n):f>=1?new t(r):new t;s.constructor=e;return s}return t.apply(this,arguments)}var r=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];function i(t,e){var r=e>1?1:0;return n[e]+Math.floor((t-1969+r)/4)-Math.floor((t-1901+r)/100)+Math.floor((t-1601+r)/400)+365*(t-1970)}function a(e){return Number(new t(1970,0,1,0,0,0,e))}for(var o in t){e[o]=t[o]}e.now=t.now;e.UTC=t.UTC;e.prototype=t.prototype;e.prototype.constructor=e;e.parse=function u(e){var n=r.exec(e);if(n){var o=Number(n[1]),u=Number(n[2]||1)-1,l=Number(n[3]||1)-1,f=Number(n[4]||0),s=Number(n[5]||0),c=Number(n[6]||0),p=Math.floor(Number(n[7]||0)*1e3),h=Boolean(n[4]&&!n[8]),v=n[9]==="-"?1:-1,g=Number(n[10]||0),y=Number(n[11]||0),d;if(f<(s>0||c>0||p>0?24:25)&&s<60&&c<60&&p<1e3&&u>-1&&u<12&&g<24&&y<60&&l>-1&&l<i(o,u+1)-i(o,u)){d=((i(o,u)+l)*24+f+g*v)*60;d=((d+s+y*v)*60+c)*1e3+p;if(h){d=a(d)}if(-864e13<=d&&d<=864e13){return d}}return NaN}return t.parse.apply(this,arguments)};return e}(Date)}if(!Date.now){Date.now=function Le(){return(new Date).getTime()}}var ne=i.toFixed&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||0xde0b6b3a7640080.toFixed(0)!=="1000000000000000128");var ie={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function Xe(t,e){var r=-1;while(++r<ie.size){e+=t*ie.data[r];ie.data[r]=e%ie.base;e=Math.floor(e/ie.base)}},divide:function Ye(t){var e=ie.size,r=0;while(--e>=0){r+=ie.data[e];ie.data[e]=Math.floor(r/t);r=r%t*ie.base}},numToString:function qe(){var t=ie.size;var e="";while(--t>=0){if(e!==""||t===0||ie.data[t]!==0){var r=String(ie.data[t]);if(e===""){e=r}else{e+="0000000".slice(0,7-r.length)+r}}}return e},pow:function Ke(t,e,r){return e===0?r:e%2===1?Ke(t,e-1,r*t):Ke(t*t,e/2,r)},log:function Qe(t){var e=0;while(t>=4096){e+=12;t/=4096}while(t>=2){e+=1;t/=2}return e}};N(i,{toFixed:function Ve(t){var e,r,n,i,a,o,u,l;e=Number(t);e=e!==e?0:Math.floor(e);if(e<0||e>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}r=Number(this);if(r!==r){return"NaN"}if(r<=-1e21||r>=1e21){return String(r)}n="";if(r<0){n="-";r=-r}i="0";if(r>1e-21){a=ie.log(r*ie.pow(2,69,1))-69;o=a<0?r*ie.pow(2,-a,1):r/ie.pow(2,a,1);o*=4503599627370496;a=52-a;if(a>0){ie.multiply(0,o);u=e;while(u>=7){ie.multiply(1e7,0);u-=7}ie.multiply(ie.pow(10,u,1),0);u=a-1;while(u>=23){ie.divide(1<<23);u-=23}ie.divide(1<<u);ie.multiply(1,1);ie.divide(2);i=ie.numToString()}else{ie.multiply(0,o);ie.multiply(1<<-a,0);i=ie.numToString()+"0.00000000000000000000".slice(2,2+e)}}if(e>0){l=i.length;if(l<=e){i=n+"0.0000000000000000000".slice(0,e-l+2)+i}else{i=n+i.slice(0,l-e)+"."+i.slice(l-e)}}else{i=n+i}return i}},ne);var ae=n.split;if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var t=typeof/()??/.exec("")[1]==="undefined";n.split=function(e,r){var n=this;if(typeof e==="undefined"&&r===0){return[]}if(!m(e)){return ae.call(this,e,r)}var i=[],a=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":""),o=0,l,f,s,c;e=new RegExp(e.source,a+"g");n+="";if(!t){l=new RegExp("^"+e.source+"$(?!\\s)",a)}r=typeof r==="undefined"?-1>>>0:D.ToUint32(r);f=e.exec(n);while(f){s=f.index+f[0].length;if(s>o){i.push(n.slice(o,f.index));if(!t&&f.length>1){f[0].replace(l,function(){for(var t=1;t<arguments.length-2;t++){if(typeof arguments[t]==="undefined"){f[t]=void 0}}})}if(f.length>1&&f.index<n.length){u.apply(i,f.slice(1))}c=f[0].length;o=s;if(i.length>=r){break}}if(e.lastIndex===f.index){e.lastIndex++}f=e.exec(n)}if(o===n.length){if(c||!e.test("")){i.push("")}}else{i.push(n.slice(o))}return i.length>r?i.slice(0,r):i}})()}else if("0".split(void 0,0).length){n.split=function We(t,e){if(typeof t==="undefined"&&e===0){return[]}return ae.call(this,t,e)}}var oe=n.replace;var ue=function(){var t=[];"x".replace(/x(.)?/g,function(e,r){t.push(r)});return t.length===1&&typeof t[0]==="undefined"}();if(!ue){n.replace=function _e(t,e){var r=h(e);var n=m(t)&&/\)[*?]/.test(t.source);if(!r||!n){return oe.call(this,t,e)}else{var i=function(r){var n=arguments.length;var i=t.lastIndex;t.lastIndex=0;var a=t.exec(r)||[];t.lastIndex=i;a.push(arguments[n-2],arguments[n-1]);return e.apply(this,a)};return oe.call(this,t,i)}}}var le=n.substr;var fe="".substr&&"0b".substr(-1)!=="b";N(n,{substr:function tr(t,e){return le.call(this,t<0?(t=this.length+t)<0?0:t:t,e)}},fe);var se=" \n\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var ce="\u200b";var pe="["+se+"]";var he=new RegExp("^"+pe+pe+"*");var ve=new RegExp(pe+pe+"*$");var ge=n.trim&&(se.trim()||!ce.trim());N(n,{trim:function er(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return String(this).replace(he,"").replace(ve,"")}},ge);if(parseInt(se+"08")!==8||parseInt(se+"0x16")!==22){parseInt=function(t){var e=/^0[xX]/;return function r(n,i){n=String(n).trim();if(!Number(i)){i=e.test(n)?16:10}return t(n,i)}}(parseInt)}});
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reactive-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.29
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Chang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -143,6 +143,7 @@ executables: []
|
|
143
143
|
extensions: []
|
144
144
|
extra_rdoc_files: []
|
145
145
|
files:
|
146
|
+
- ".codeclimate.yml"
|
146
147
|
- ".gitignore"
|
147
148
|
- ".travis.yml"
|
148
149
|
- Gemfile
|
@@ -248,51 +249,67 @@ files:
|
|
248
249
|
- example/todos/vendor/base.css
|
249
250
|
- example/todos/vendor/bg.png
|
250
251
|
- example/todos/vendor/jquery.js
|
252
|
+
- lib/generators/reactive_ruby/test_app/templates/application.rb
|
253
|
+
- lib/generators/reactive_ruby/test_app/templates/assets/javascripts/application.rb
|
254
|
+
- lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb
|
255
|
+
- lib/generators/reactive_ruby/test_app/templates/boot.rb
|
256
|
+
- lib/generators/reactive_ruby/test_app/templates/script/rails
|
257
|
+
- lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb
|
258
|
+
- lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb
|
259
|
+
- lib/generators/reactive_ruby/test_app/test_app_generator.rb
|
251
260
|
- lib/rails-helpers/top_level_rails_component.rb
|
261
|
+
- lib/react/api.rb
|
262
|
+
- lib/react/callbacks.rb
|
263
|
+
- lib/react/component.rb
|
264
|
+
- lib/react/component/api.rb
|
265
|
+
- lib/react/component/class_methods.rb
|
266
|
+
- lib/react/element.rb
|
267
|
+
- lib/react/event.rb
|
268
|
+
- lib/react/ext/hash.rb
|
269
|
+
- lib/react/ext/string.rb
|
270
|
+
- lib/react/native_library.rb
|
271
|
+
- lib/react/observable.rb
|
272
|
+
- lib/react/rendering_context.rb
|
273
|
+
- lib/react/state.rb
|
274
|
+
- lib/react/top_level.rb
|
275
|
+
- lib/react/validator.rb
|
252
276
|
- lib/reactive-ruby.rb
|
253
|
-
- lib/reactive-ruby/api.rb
|
254
|
-
- lib/reactive-ruby/callbacks.rb
|
255
|
-
- lib/reactive-ruby/component.rb
|
256
277
|
- lib/reactive-ruby/component_loader.rb
|
257
|
-
- lib/reactive-ruby/element.rb
|
258
|
-
- lib/reactive-ruby/event.rb
|
259
|
-
- lib/reactive-ruby/ext/hash.rb
|
260
|
-
- lib/reactive-ruby/ext/string.rb
|
261
278
|
- lib/reactive-ruby/isomorphic_helpers.rb
|
262
|
-
- lib/reactive-ruby/observable.rb
|
263
279
|
- lib/reactive-ruby/rails.rb
|
264
280
|
- lib/reactive-ruby/rails/component_mount.rb
|
265
281
|
- lib/reactive-ruby/rails/controller_helper.rb
|
266
282
|
- lib/reactive-ruby/rails/railtie.rb
|
267
|
-
- lib/reactive-ruby/rendering_context.rb
|
268
283
|
- lib/reactive-ruby/serializers.rb
|
269
284
|
- lib/reactive-ruby/server_rendering/contextual_renderer.rb
|
270
|
-
- lib/reactive-ruby/state.rb
|
271
|
-
- lib/reactive-ruby/top_level.rb
|
272
|
-
- lib/reactive-ruby/validator.rb
|
273
285
|
- lib/reactive-ruby/version.rb
|
274
286
|
- lib/sources/react.js
|
275
287
|
- lib/sources/react.js-v12
|
276
288
|
- logo1.png
|
277
289
|
- logo2.png
|
278
290
|
- logo3.png
|
279
|
-
- old-readme
|
280
|
-
- opal-spec/callbacks_spec.rb
|
281
|
-
- opal-spec/component_spec.rb
|
282
|
-
- opal-spec/element_spec.rb
|
283
|
-
- opal-spec/event_spec.rb
|
284
|
-
- opal-spec/react_spec.rb
|
285
|
-
- opal-spec/reactjs/index.html.erb
|
286
|
-
- opal-spec/spec_helper.rb
|
287
|
-
- opal-spec/tutorial/tutorial_spec.rb
|
288
|
-
- opal-spec/validator_spec.rb
|
289
291
|
- reactive-ruby.gemspec
|
290
292
|
- spec/controller_helper_spec.rb
|
293
|
+
- spec/index.html.erb
|
294
|
+
- spec/react/callbacks_spec.rb
|
295
|
+
- spec/react/component_spec.rb
|
296
|
+
- spec/react/dsl_spec.rb
|
297
|
+
- spec/react/element_spec.rb
|
298
|
+
- spec/react/event_spec.rb
|
299
|
+
- spec/react/native_library_spec.rb
|
300
|
+
- spec/react/param_declaration_spec.rb
|
301
|
+
- spec/react/react_spec.rb
|
302
|
+
- spec/react/react_state_spec.rb
|
303
|
+
- spec/react/top_level_component_spec.rb
|
304
|
+
- spec/react/tutorial/tutorial_spec.rb
|
305
|
+
- spec/react/validator_spec.rb
|
291
306
|
- spec/reactive-ruby/component_loader_spec.rb
|
292
307
|
- spec/reactive-ruby/isomorphic_helpers_spec.rb
|
293
308
|
- spec/reactive-ruby/rails/component_mount_spec.rb
|
294
309
|
- spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb
|
295
310
|
- spec/spec_helper.rb
|
311
|
+
- spec/support/react/spec_helpers.rb
|
312
|
+
- spec/vendor/es5-shim.min.js
|
296
313
|
homepage: https://github.com/zetachang/react.rb
|
297
314
|
licenses:
|
298
315
|
- MIT
|
@@ -319,8 +336,23 @@ specification_version: 4
|
|
319
336
|
summary: Opal Ruby wrapper of React.js library.
|
320
337
|
test_files:
|
321
338
|
- spec/controller_helper_spec.rb
|
339
|
+
- spec/index.html.erb
|
340
|
+
- spec/react/callbacks_spec.rb
|
341
|
+
- spec/react/component_spec.rb
|
342
|
+
- spec/react/dsl_spec.rb
|
343
|
+
- spec/react/element_spec.rb
|
344
|
+
- spec/react/event_spec.rb
|
345
|
+
- spec/react/native_library_spec.rb
|
346
|
+
- spec/react/param_declaration_spec.rb
|
347
|
+
- spec/react/react_spec.rb
|
348
|
+
- spec/react/react_state_spec.rb
|
349
|
+
- spec/react/top_level_component_spec.rb
|
350
|
+
- spec/react/tutorial/tutorial_spec.rb
|
351
|
+
- spec/react/validator_spec.rb
|
322
352
|
- spec/reactive-ruby/component_loader_spec.rb
|
323
353
|
- spec/reactive-ruby/isomorphic_helpers_spec.rb
|
324
354
|
- spec/reactive-ruby/rails/component_mount_spec.rb
|
325
355
|
- spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb
|
326
356
|
- spec/spec_helper.rb
|
357
|
+
- spec/support/react/spec_helpers.rb
|
358
|
+
- spec/vendor/es5-shim.min.js
|
@@ -1,502 +0,0 @@
|
|
1
|
-
require "reactive-ruby/ext/string"
|
2
|
-
require 'active_support/core_ext/class/attribute'
|
3
|
-
require 'reactive-ruby/callbacks'
|
4
|
-
require "reactive-ruby/ext/hash"
|
5
|
-
require "reactive-ruby/rendering_context"
|
6
|
-
require "reactive-ruby/observable"
|
7
|
-
require "reactive-ruby/state"
|
8
|
-
|
9
|
-
require 'native'
|
10
|
-
|
11
|
-
module React
|
12
|
-
module Component
|
13
|
-
|
14
|
-
def self.included(base)
|
15
|
-
base.include(API)
|
16
|
-
base.include(React::Callbacks)
|
17
|
-
base.class_eval do
|
18
|
-
class_attribute :initial_state
|
19
|
-
define_callback :before_mount
|
20
|
-
define_callback :after_mount
|
21
|
-
define_callback :before_receive_props
|
22
|
-
define_callback :before_update
|
23
|
-
define_callback :after_update
|
24
|
-
define_callback :before_unmount
|
25
|
-
|
26
|
-
def render
|
27
|
-
raise "no render defined"
|
28
|
-
end unless method_defined? :render
|
29
|
-
|
30
|
-
def children
|
31
|
-
nodes = [`#{@native}.props.children`].flatten
|
32
|
-
class << nodes
|
33
|
-
include Enumerable
|
34
|
-
|
35
|
-
def to_n
|
36
|
-
self
|
37
|
-
end
|
38
|
-
|
39
|
-
def each(&block)
|
40
|
-
if block_given?
|
41
|
-
%x{
|
42
|
-
React.Children.forEach(#{self.to_n}, function(context){
|
43
|
-
#{block.call(React::Element.new(`context`))}
|
44
|
-
})
|
45
|
-
}
|
46
|
-
nil
|
47
|
-
else
|
48
|
-
Enumerator.new(`React.Children.count(#{self.to_n})`) do |y|
|
49
|
-
%x{
|
50
|
-
React.Children.forEach(#{self.to_n}, function(context){
|
51
|
-
#{y << React::Element.new(`context`)}
|
52
|
-
})
|
53
|
-
}
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
nodes
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
base.extend(ClassMethods)
|
64
|
-
|
65
|
-
if base.name
|
66
|
-
parent = base.name.split("::").inject([Module]) { |nesting, next_const| nesting + [nesting.last.const_get(next_const)] }[-2]
|
67
|
-
|
68
|
-
class << parent
|
69
|
-
|
70
|
-
def method_missing(n, *args, &block)
|
71
|
-
name = n
|
72
|
-
if name =~ /_as_node$/
|
73
|
-
node_only = true
|
74
|
-
name = name.gsub(/_as_node$/, "")
|
75
|
-
end
|
76
|
-
begin
|
77
|
-
name = const_get(name)
|
78
|
-
rescue Exception
|
79
|
-
name = nil
|
80
|
-
end
|
81
|
-
unless name and name.method_defined? :render
|
82
|
-
return super
|
83
|
-
end
|
84
|
-
if node_only
|
85
|
-
React::RenderingContext.build { React::RenderingContext.render(name, *args, &block) }.to_n
|
86
|
-
else
|
87
|
-
React::RenderingContext.render(name, *args, &block)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def initialize(native_element)
|
96
|
-
@native = native_element
|
97
|
-
end
|
98
|
-
|
99
|
-
def params
|
100
|
-
Hash.new(`#{@native}.props`)
|
101
|
-
end
|
102
|
-
|
103
|
-
def refs
|
104
|
-
Hash.new(`#{@native}.refs`)
|
105
|
-
end
|
106
|
-
|
107
|
-
def state
|
108
|
-
raise "No native ReactComponent associated" unless @native
|
109
|
-
Hash.new(`#{@native}.state`)
|
110
|
-
end
|
111
|
-
|
112
|
-
def update_react_js_state(object, name, value)
|
113
|
-
set_state({"***_state_updated_at-***" => Time.now.to_f, "#{object.class.to_s+'.' unless object == self}#{name}" => value}) rescue nil
|
114
|
-
end
|
115
|
-
|
116
|
-
def emit(event_name, *args)
|
117
|
-
self.params["_on#{event_name.to_s.event_camelize}"].call(*args)
|
118
|
-
end
|
119
|
-
|
120
|
-
def component_will_mount
|
121
|
-
IsomorphicHelpers.load_context(true) if IsomorphicHelpers.on_opal_client?
|
122
|
-
@processed_params = {}
|
123
|
-
React::State.initialize_states(self, initial_state)
|
124
|
-
React::State.set_state_context_to(self) { self.run_callback(:before_mount) }
|
125
|
-
rescue Exception => e
|
126
|
-
self.class.process_exception(e, self)
|
127
|
-
end
|
128
|
-
|
129
|
-
def component_did_mount
|
130
|
-
React::State.set_state_context_to(self) do
|
131
|
-
self.run_callback(:after_mount)
|
132
|
-
React::State.update_states_to_observe
|
133
|
-
end
|
134
|
-
rescue Exception => e
|
135
|
-
self.class.process_exception(e, self)
|
136
|
-
end
|
137
|
-
|
138
|
-
def component_will_receive_props(next_props)
|
139
|
-
# need to rethink how this works in opal-react, or if its actually that useful within the react.rb environment
|
140
|
-
# for now we are just using it to clear processed_params
|
141
|
-
React::State.set_state_context_to(self) { self.run_callback(:before_receive_props, Hash.new(next_props)) }
|
142
|
-
@processed_params = {}
|
143
|
-
rescue Exception => e
|
144
|
-
self.class.process_exception(e, self)
|
145
|
-
end
|
146
|
-
|
147
|
-
def props_changed?(next_props)
|
148
|
-
return true unless params.keys.sort == next_props.keys.sort
|
149
|
-
params.detect { |k, v| `#{next_props[k]} != #{params[k]}`}
|
150
|
-
end
|
151
|
-
|
152
|
-
def should_component_update?(next_props, next_state)
|
153
|
-
React::State.set_state_context_to(self) do
|
154
|
-
next_props = Hash.new(next_props)
|
155
|
-
if self.respond_to?(:needs_update?)
|
156
|
-
!!self.needs_update?(next_props, Hash.new(next_state))
|
157
|
-
elsif false # switch to true to force updates per standard react
|
158
|
-
true
|
159
|
-
elsif props_changed? next_props
|
160
|
-
true
|
161
|
-
elsif `!next_state != !#{@native}.state`
|
162
|
-
true
|
163
|
-
elsif `!next_state && !#{@native}.state`
|
164
|
-
false
|
165
|
-
elsif `next_state["***_state_updated_at-***"] != #{@native}.state["***_state_updated_at-***"]`
|
166
|
-
true
|
167
|
-
else
|
168
|
-
false
|
169
|
-
end.to_n
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def component_will_update(next_props, next_state)
|
174
|
-
React::State.set_state_context_to(self) { self.run_callback(:before_update, Hash.new(next_props), Hash.new(next_state)) }
|
175
|
-
rescue Exception => e
|
176
|
-
self.class.process_exception(e, self)
|
177
|
-
end
|
178
|
-
|
179
|
-
|
180
|
-
def component_did_update(prev_props, prev_state)
|
181
|
-
React::State.set_state_context_to(self) do
|
182
|
-
self.run_callback(:after_update, Hash.new(prev_props), Hash.new(prev_state))
|
183
|
-
React::State.update_states_to_observe
|
184
|
-
end
|
185
|
-
rescue Exception => e
|
186
|
-
self.class.process_exception(e, self)
|
187
|
-
end
|
188
|
-
|
189
|
-
def component_will_unmount
|
190
|
-
React::State.set_state_context_to(self) do
|
191
|
-
self.run_callback(:before_unmount)
|
192
|
-
React::State.remove
|
193
|
-
end
|
194
|
-
rescue Exception => e
|
195
|
-
self.class.process_exception(e, self)
|
196
|
-
end
|
197
|
-
|
198
|
-
def p(*args, &block)
|
199
|
-
if block || args.count == 0 || (args.count == 1 && args.first.is_a?(Hash))
|
200
|
-
_p_tag(*args, &block)
|
201
|
-
else
|
202
|
-
Kernel.p(*args)
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def component?(name)
|
207
|
-
name_list = name.split("::")
|
208
|
-
scope_list = self.class.name.split("::").inject([Module]) { |nesting, next_const| nesting + [nesting.last.const_get(next_const)] }.reverse
|
209
|
-
scope_list.each do |scope|
|
210
|
-
component = name_list.inject(scope) do |scope, class_name|
|
211
|
-
scope.const_get(class_name)
|
212
|
-
end rescue nil
|
213
|
-
return component if component and component.method_defined? :render
|
214
|
-
end
|
215
|
-
nil
|
216
|
-
end
|
217
|
-
|
218
|
-
def method_missing(n, *args, &block)
|
219
|
-
return params[n] if params.key? n
|
220
|
-
name = n
|
221
|
-
if name =~ /_as_node$/
|
222
|
-
node_only = true
|
223
|
-
name = name.gsub(/_as_node$/, "")
|
224
|
-
end
|
225
|
-
unless (React::HTML_TAGS.include?(name) || name == 'present' || name == '_p_tag' || (name = component?(name, self)))
|
226
|
-
return super
|
227
|
-
end
|
228
|
-
|
229
|
-
if name == "present"
|
230
|
-
name = args.shift
|
231
|
-
end
|
232
|
-
|
233
|
-
if name == "_p_tag"
|
234
|
-
name = "p"
|
235
|
-
end
|
236
|
-
|
237
|
-
if node_only
|
238
|
-
React::RenderingContext.build { React::RenderingContext.render(name, *args, &block) }.to_n
|
239
|
-
else
|
240
|
-
React::RenderingContext.render(name, *args, &block)
|
241
|
-
end
|
242
|
-
|
243
|
-
end
|
244
|
-
|
245
|
-
def watch(value, &on_change)
|
246
|
-
React::Observable.new(value, on_change)
|
247
|
-
end
|
248
|
-
|
249
|
-
def define_state(*args, &block)
|
250
|
-
React::State.initialize_states(self, self.class.define_state(*args, &block))
|
251
|
-
end
|
252
|
-
|
253
|
-
attr_reader :waiting_on_resources
|
254
|
-
|
255
|
-
def _render_wrapper
|
256
|
-
React::State.set_state_context_to(self) do
|
257
|
-
RenderingContext.render(nil) {render || ""}.tap { |element| @waiting_on_resources = element.waiting_on_resources if element.respond_to? :waiting_on_resources }
|
258
|
-
end
|
259
|
-
rescue Exception => e
|
260
|
-
self.class.process_exception(e, self)
|
261
|
-
end
|
262
|
-
|
263
|
-
module ClassMethods
|
264
|
-
|
265
|
-
def backtrace(*args)
|
266
|
-
@backtrace_off = (args[0] == :off)
|
267
|
-
end
|
268
|
-
|
269
|
-
def process_exception(e, component, reraise = nil)
|
270
|
-
message = ["Exception raised while rendering #{component}"]
|
271
|
-
if !@backtrace_off
|
272
|
-
message << " #{e.backtrace[0]}"
|
273
|
-
message += e.backtrace[1..-1].collect { |line| line }
|
274
|
-
else
|
275
|
-
message[0] += ": #{e.message}"
|
276
|
-
end
|
277
|
-
message = message.join("\n")
|
278
|
-
`console.error(message)`
|
279
|
-
raise e if reraise
|
280
|
-
end
|
281
|
-
|
282
|
-
def validator
|
283
|
-
@validator ||= React::Validator.new
|
284
|
-
end
|
285
|
-
|
286
|
-
def prop_types
|
287
|
-
if self.validator
|
288
|
-
{
|
289
|
-
_componentValidator: %x{
|
290
|
-
function(props, propName, componentName) {
|
291
|
-
var errors = #{validator.validate(Hash.new(`props`))};
|
292
|
-
var error = new Error(#{"In component `" + self.name + "`\n" + `errors`.join("\n")});
|
293
|
-
return #{`errors`.count > 0 ? `error` : `undefined`};
|
294
|
-
}
|
295
|
-
}
|
296
|
-
}
|
297
|
-
else
|
298
|
-
{}
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
def default_props
|
303
|
-
validator.default_props
|
304
|
-
end
|
305
|
-
|
306
|
-
def params(&block)
|
307
|
-
validator.build(&block)
|
308
|
-
end
|
309
|
-
|
310
|
-
def define_param_method(name, param_type)
|
311
|
-
if param_type == React::Observable
|
312
|
-
(@two_way_params ||= []) << name
|
313
|
-
define_method("#{name}") do
|
314
|
-
params[name].instance_variable_get("@value") if params[name]
|
315
|
-
end
|
316
|
-
define_method("#{name}!") do |*args|
|
317
|
-
return unless params[name]
|
318
|
-
if args.count > 0
|
319
|
-
current_value = params[name].instance_variable_get("@value")
|
320
|
-
params[name].call args[0]
|
321
|
-
current_value
|
322
|
-
else
|
323
|
-
current_value = params[name].instance_variable_get("@value")
|
324
|
-
params[name].call current_value unless @dont_update_state rescue nil # rescue in case we in middle of render
|
325
|
-
params[name]
|
326
|
-
end
|
327
|
-
end
|
328
|
-
elsif param_type == Proc
|
329
|
-
define_method("#{name}") do |*args, &block|
|
330
|
-
params[name].call(*args, &block) if params[name]
|
331
|
-
end
|
332
|
-
else
|
333
|
-
define_method("#{name}") do
|
334
|
-
@processed_params[name] ||= if param_type.respond_to? :_react_param_conversion
|
335
|
-
param_type._react_param_conversion params[name]
|
336
|
-
elsif param_type.is_a? Array and param_type[0].respond_to? :_react_param_conversion
|
337
|
-
params[name].collect { |param| param_type[0]._react_param_conversion param }
|
338
|
-
else
|
339
|
-
params[name]
|
340
|
-
end
|
341
|
-
end
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
def required_param(name, options = {})
|
346
|
-
validator.requires(name, options)
|
347
|
-
define_param_method(name, options[:type])
|
348
|
-
end
|
349
|
-
|
350
|
-
alias_method :require_param, :required_param
|
351
|
-
|
352
|
-
def optional_param(name, options = {})
|
353
|
-
validator.optional(name, options)
|
354
|
-
define_param_method(name, options[:type]) unless name == :params
|
355
|
-
end
|
356
|
-
|
357
|
-
def collect_other_params_as(name)
|
358
|
-
validator.all_others(name)
|
359
|
-
define_method(name) do
|
360
|
-
@_all_others ||= self.class.validator.collect_all_others(params)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
def define_state(*states, &block)
|
365
|
-
default_initial_value = (block and block.arity == 0) ? yield : nil
|
366
|
-
states_hash = (states.last.is_a? Hash) ? states.pop : {}
|
367
|
-
states.each { |name| states_hash[name] = default_initial_value }
|
368
|
-
(self.initial_state ||= {}).merge! states_hash
|
369
|
-
states_hash.each do |name, initial_value|
|
370
|
-
define_state_methods(self, name, &block)
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
def export_state(*states, &block)
|
375
|
-
default_initial_value = (block and block.arity == 0) ? yield : nil
|
376
|
-
states_hash = (states.last.is_a? Hash) ? states.pop : {}
|
377
|
-
states.each { |name| states_hash[name] = default_initial_value }
|
378
|
-
React::State.initialize_states(self, states_hash)
|
379
|
-
states_hash.each do |name, initial_value|
|
380
|
-
define_state_methods(self, name, self, &block)
|
381
|
-
define_state_methods(singleton_class, name, self, &block)
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
385
|
-
def define_state_methods(this, name, from = nil, &block)
|
386
|
-
this.define_method("#{name}") do
|
387
|
-
React::State.get_state(from || self, name)
|
388
|
-
end
|
389
|
-
this.define_method("#{name}=") do |new_state|
|
390
|
-
yield name, React::State.get_state(from || self, name), new_state if block and block.arity > 0
|
391
|
-
React::State.set_state(from || self, name, new_state)
|
392
|
-
end
|
393
|
-
this.define_method("#{name}!") do |*args|
|
394
|
-
#return unless @native
|
395
|
-
if args.count > 0
|
396
|
-
yield name, React::State.get_state(from || self, name), args[0] if block and block.arity > 0
|
397
|
-
current_value = React::State.get_state(from || self, name)
|
398
|
-
React::State.set_state(from || self, name, args[0])
|
399
|
-
current_value
|
400
|
-
else
|
401
|
-
current_state = React::State.get_state(from || self, name)
|
402
|
-
yield name, React::State.get_state(from || self, name), current_state if block and block.arity > 0
|
403
|
-
React::State.set_state(from || self, name, current_state)
|
404
|
-
React::Observable.new(current_state) do |update|
|
405
|
-
yield name, React::State.get_state(from || self, name), update if block and block.arity > 0
|
406
|
-
React::State.set_state(from || self, name, update)
|
407
|
-
end
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
def native_mixin(item)
|
413
|
-
native_mixins << item
|
414
|
-
end
|
415
|
-
|
416
|
-
def native_mixins
|
417
|
-
@native_mixins ||= []
|
418
|
-
end
|
419
|
-
|
420
|
-
def static_call_back(name, &block)
|
421
|
-
static_call_backs[name] = block
|
422
|
-
end
|
423
|
-
|
424
|
-
def static_call_backs
|
425
|
-
@static_call_backs ||= {}
|
426
|
-
end
|
427
|
-
|
428
|
-
def export_component(opts = {})
|
429
|
-
export_name = (opts[:as] || name).split("::")
|
430
|
-
first_name = export_name.first
|
431
|
-
Native(`window`)[first_name] = add_item_to_tree(Native(`window`)[first_name], [React::API.create_native_react_class(self)] + export_name[1..-1].reverse).to_n
|
432
|
-
end
|
433
|
-
|
434
|
-
def add_item_to_tree(current_tree, new_item)
|
435
|
-
if Native(current_tree).class != Native::Object or new_item.length == 1
|
436
|
-
new_item.inject do |memo, sub_name| {sub_name => memo} end
|
437
|
-
else
|
438
|
-
Native(current_tree)[new_item.last] = add_item_to_tree(Native(current_tree)[new_item.last], new_item[0..-2])
|
439
|
-
current_tree
|
440
|
-
end
|
441
|
-
end
|
442
|
-
|
443
|
-
end
|
444
|
-
|
445
|
-
module API
|
446
|
-
#include Native
|
447
|
-
|
448
|
-
def dom_node
|
449
|
-
if `typeof React.findDOMNode === 'undefined'`
|
450
|
-
`#{self}.native.getDOMNode` # v0.12.0
|
451
|
-
else
|
452
|
-
`React.findDOMNode(#{self}.native)` # v0.13.0
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
def mounted?
|
457
|
-
`#{self}.native.isMounted()`
|
458
|
-
end
|
459
|
-
|
460
|
-
def force_update!
|
461
|
-
`#{self}.native.forceUpdate()`
|
462
|
-
end
|
463
|
-
|
464
|
-
def set_props(prop, &block)
|
465
|
-
raise "No native ReactComponent associated" unless @native
|
466
|
-
%x{
|
467
|
-
#{@native}.setProps(#{prop.shallow_to_n}, function(){
|
468
|
-
#{block.call if block}
|
469
|
-
});
|
470
|
-
}
|
471
|
-
end
|
472
|
-
|
473
|
-
def set_props!(prop, &block)
|
474
|
-
raise "No native ReactComponent associated" unless @native
|
475
|
-
%x{
|
476
|
-
#{@native}.replaceProps(#{prop.shallow_to_n}, function(){
|
477
|
-
#{block.call if block}
|
478
|
-
});
|
479
|
-
}
|
480
|
-
end
|
481
|
-
|
482
|
-
def set_state(state, &block)
|
483
|
-
raise "No native ReactComponent associated" unless @native
|
484
|
-
%x{
|
485
|
-
#{@native}.setState(#{state.shallow_to_n}, function(){
|
486
|
-
#{block.call if block}
|
487
|
-
});
|
488
|
-
}
|
489
|
-
end
|
490
|
-
|
491
|
-
def set_state!(state, &block)
|
492
|
-
raise "No native ReactComponent associated" unless @native
|
493
|
-
%x{
|
494
|
-
#{@native}.replaceState(#{state.shallow_to_n}, function(){
|
495
|
-
#{block.call if block}
|
496
|
-
});
|
497
|
-
}
|
498
|
-
end
|
499
|
-
end
|
500
|
-
|
501
|
-
end
|
502
|
-
end
|