hyper-react 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +11 -0
- data/Appraisals +10 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile +2 -0
- data/README.md +7 -0
- data/gemfiles/opal_0.10_react_13.gemfile +4 -0
- data/gemfiles/opal_0.10_react_14.gemfile +4 -0
- data/gemfiles/opal_0.10_react_15.gemfile +4 -0
- data/gemfiles/opal_0.8_react_13.gemfile +4 -0
- data/gemfiles/opal_0.8_react_14.gemfile +4 -0
- data/gemfiles/opal_0.8_react_15.gemfile +4 -0
- data/gemfiles/opal_0.9_react_13.gemfile +4 -0
- data/gemfiles/opal_0.9_react_14.gemfile +4 -0
- data/gemfiles/opal_0.9_react_15.gemfile +4 -0
- data/gemfiles/opal_master_react_15.gemfile +18 -0
- data/hyper-react.gemspec +4 -0
- data/lib/hyper-react.rb +24 -4
- data/lib/rails-helpers/top_level_rails_component.rb +1 -1
- data/lib/react/api.rb +10 -0
- data/lib/react/component.rb +135 -106
- data/lib/react/component/base.rb +5 -1
- data/lib/react/component/class_methods.rb +12 -37
- data/lib/react/component/dsl_instance_methods.rb +0 -4
- data/lib/react/component/props_wrapper.rb +0 -5
- data/lib/react/component/should_component_update.rb +1 -5
- data/lib/react/component/tags.rb +7 -22
- data/lib/react/config.rb +5 -0
- data/lib/react/config/client.rb.erb +19 -0
- data/lib/react/config/server.rb +20 -0
- data/lib/react/element.rb +1 -0
- data/lib/react/native_library.rb +2 -7
- data/lib/react/react-source-browser.rb +3 -0
- data/lib/react/react-source-server.rb +3 -0
- data/lib/react/react-source.rb +12 -1
- data/lib/react/ref_callback.rb +31 -0
- data/lib/react/rendering_context.rb +9 -9
- data/lib/react/server.rb +23 -0
- data/lib/react/state_wrapper.rb +23 -0
- data/lib/react/test/matchers/render_html_matcher.rb +4 -2
- data/lib/react/top_level.rb +2 -0
- data/lib/reactive-ruby/component_loader.rb +2 -1
- data/lib/reactive-ruby/isomorphic_helpers.rb +10 -0
- data/lib/reactive-ruby/version.rb +1 -1
- data/lib/reactrb/auto-import.rb +2 -7
- data/spec/react/callbacks_spec.rb +8 -7
- data/spec/react/component_spec.rb +24 -13
- data/spec/react/dsl_spec.rb +12 -8
- data/spec/react/element_spec.rb +7 -7
- data/spec/react/native_library_spec.rb +25 -43
- data/spec/react/param_declaration_spec.rb +9 -0
- data/spec/react/react_spec.rb +0 -7
- data/spec/react/refs_callback_spec.rb +56 -0
- data/spec/react/server_spec.rb +25 -0
- data/spec/react/state_spec.rb +3 -3
- data/spec/react/top_level_component_spec.rb +1 -1
- data/spec/spec_helper.rb +31 -1
- metadata +72 -9
- data/lib/react/observable.rb +0 -29
- data/lib/react/state.rb +0 -191
- data/lib/sources/react-latest.js +0 -21169
- data/lib/sources/react-v13.js +0 -21645
- data/lib/sources/react-v14.js +0 -20821
- data/lib/sources/react-v15.js +0 -21170
|
@@ -66,7 +66,16 @@ describe 'the param macro', type: :component do
|
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
%x{
|
|
70
|
+
var log = [];
|
|
71
|
+
var org_warn_console = window.console.warn;
|
|
72
|
+
var org_error_console = window.console.error;
|
|
73
|
+
window.console.warn = window.console.error = function(str){log.push(str)}
|
|
74
|
+
}
|
|
69
75
|
expect(Foo).to render_static_html('<div>12-string</div>').with_params(foo1: 12, foo2: "string")
|
|
76
|
+
`window.console.warn = org_warn_console; window.console.error = org_error_console;`
|
|
77
|
+
|
|
78
|
+
expect(`log[0]`).to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo1` could not be converted to String/)
|
|
70
79
|
end
|
|
71
80
|
|
|
72
81
|
it 'logs error in warning if validation failed' do
|
data/spec/react/react_spec.rb
CHANGED
|
@@ -201,13 +201,6 @@ RSpec.describe React, type: :component do
|
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
|
|
204
|
-
describe "render_to_string" do
|
|
205
|
-
it "should render a React.Element to string" do
|
|
206
|
-
ele = React.create_element('span') { "lorem" }
|
|
207
|
-
expect(React.render_to_string(ele)).to be_kind_of(String)
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
204
|
describe "unmount_component_at_node" do
|
|
212
205
|
async "should unmount component at node" do
|
|
213
206
|
div = `document.createElement("div")`
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
|
|
5
|
+
describe 'Refs callback' do
|
|
6
|
+
before do
|
|
7
|
+
stub_const 'Foo', Class.new
|
|
8
|
+
Foo.class_eval do
|
|
9
|
+
include React::Component
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "is invoked with the actual Ruby instance" do
|
|
14
|
+
stub_const 'Bar', Class.new
|
|
15
|
+
Bar.class_eval do
|
|
16
|
+
include React::Component
|
|
17
|
+
def render
|
|
18
|
+
React.create_element('div')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Foo.class_eval do
|
|
23
|
+
def my_bar=(bar)
|
|
24
|
+
$bar = bar
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def render
|
|
28
|
+
React.create_element(Bar, ref: method(:my_bar=).to_proc)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
element = React.create_element(Foo)
|
|
33
|
+
React::Test::Utils.render_into_document(element)
|
|
34
|
+
expect($bar).to be_a(Bar)
|
|
35
|
+
$bar = nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "is invoked with the actual DOM node" do
|
|
39
|
+
Foo.class_eval do
|
|
40
|
+
def my_div=(div)
|
|
41
|
+
$div = div
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def render
|
|
45
|
+
React.create_element('div', ref: method(:my_div=).to_proc)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
element = React.create_element(Foo)
|
|
50
|
+
React::Test::Utils.render_into_document(element)
|
|
51
|
+
expect(`#{$div}.nodeType`).to eq(1)
|
|
52
|
+
$div = nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
if opal?
|
|
4
|
+
|
|
5
|
+
RSpec.describe React::Server do
|
|
6
|
+
after(:each) do
|
|
7
|
+
React::API.clear_component_class_cache
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "render_to_string" do
|
|
11
|
+
it "should render a React.Element to string" do
|
|
12
|
+
ele = React.create_element('span') { "lorem" }
|
|
13
|
+
expect(React::Server.render_to_string(ele)).to be_kind_of(String)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "render_to_static_markup" do
|
|
18
|
+
it "should render a React.Element to static markup" do
|
|
19
|
+
ele = React.create_element('span') { "lorem" }
|
|
20
|
+
expect(React::Server.render_to_static_markup(ele)).to eq("<span>lorem</span>")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
data/spec/react/state_spec.rb
CHANGED
|
@@ -2,13 +2,13 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
if opal?
|
|
4
4
|
describe 'React::State' do
|
|
5
|
-
it "can
|
|
5
|
+
it "can create dynamically initialized exported states" do
|
|
6
6
|
stub_const 'Foo', Class.new
|
|
7
7
|
Foo.class_eval do
|
|
8
8
|
include React::Component
|
|
9
9
|
export_state(:foo) { 'bar' }
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
Hyperloop::Application::Boot.run
|
|
12
12
|
expect(Foo.foo).to eq('bar')
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -45,7 +45,7 @@ describe 'React::State' do
|
|
|
45
45
|
var org_error_console = window.console.error;
|
|
46
46
|
window.console.warn = window.console.error = function(str){log.push(str)}
|
|
47
47
|
}
|
|
48
|
-
markup = React.render_to_static_markup(React.create_element(StateTest))
|
|
48
|
+
markup = React::Server.render_to_static_markup(React.create_element(StateTest))
|
|
49
49
|
`window.console.warn = org_warn_console; window.console.error = org_error_console;`
|
|
50
50
|
expect(markup).to eq('<span>Boom</span>')
|
|
51
51
|
expect(StateTest.boom).to be_falsy
|
|
@@ -45,7 +45,7 @@ def render_top_level(controller, component_name)
|
|
|
45
45
|
render_params: {}
|
|
46
46
|
}
|
|
47
47
|
element = React.create_element(React::TopLevelRailsComponent, params)
|
|
48
|
-
React.render_to_static_markup(element)
|
|
48
|
+
React::Server.render_to_static_markup(element)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
describe React::TopLevelRailsComponent do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -15,14 +15,44 @@ end
|
|
|
15
15
|
|
|
16
16
|
if RUBY_ENGINE == 'opal'
|
|
17
17
|
require File.expand_path('../vendor/jquery-2.2.4.min', __FILE__)
|
|
18
|
-
require 'react/react-source'
|
|
18
|
+
require 'react/react-source-browser'
|
|
19
|
+
require 'react/react-source-server'
|
|
19
20
|
require 'hyper-react'
|
|
20
21
|
require 'react/test/rspec'
|
|
21
22
|
require 'react/test/utils'
|
|
22
23
|
require 'react/top_level_render'
|
|
24
|
+
require 'react/ref_callback'
|
|
25
|
+
require 'react/server'
|
|
23
26
|
|
|
24
27
|
require File.expand_path('../support/react/spec_helpers', __FILE__)
|
|
25
28
|
|
|
29
|
+
# turn off deprecation warnings for old style name spaces during this test
|
|
30
|
+
module React
|
|
31
|
+
module Component
|
|
32
|
+
|
|
33
|
+
def self.included(base)
|
|
34
|
+
# deprecation_warning base, "The module name React::Component has been deprecated. Use Hyperloop::Component::Mixin instead."
|
|
35
|
+
base.include Hyperloop::Component::Mixin
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Base
|
|
39
|
+
def self.inherited(child)
|
|
40
|
+
# unless child.to_s == "React::Component::HyperTestDummy"
|
|
41
|
+
# React::Component.deprecation_warning child, "The class name React::Component::Base has been deprecated. Use Hyperloop::Component instead."
|
|
42
|
+
# end
|
|
43
|
+
child.include(ComponentNoNotice)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module React
|
|
50
|
+
class State
|
|
51
|
+
# this messes with lots of tests, these tests will be retested in the new hyper-component gem tests
|
|
52
|
+
ALWAYS_UPDATE_STATE_AFTER_RENDER = false
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
26
56
|
module Opal
|
|
27
57
|
module RSpec
|
|
28
58
|
module AsyncHelpers
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hyper-react
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Chang
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2017-03-13 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: opal
|
|
@@ -54,6 +54,34 @@ dependencies:
|
|
|
54
54
|
- - ">="
|
|
55
55
|
- !ruby/object:Gem::Version
|
|
56
56
|
version: '0'
|
|
57
|
+
- !ruby/object:Gem::Dependency
|
|
58
|
+
name: hyper-store
|
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '0'
|
|
64
|
+
type: :runtime
|
|
65
|
+
prerelease: false
|
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '0'
|
|
71
|
+
- !ruby/object:Gem::Dependency
|
|
72
|
+
name: hyperloop-config
|
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
type: :runtime
|
|
79
|
+
prerelease: false
|
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
81
|
+
requirements:
|
|
82
|
+
- - ">="
|
|
83
|
+
- !ruby/object:Gem::Version
|
|
84
|
+
version: '0'
|
|
57
85
|
- !ruby/object:Gem::Dependency
|
|
58
86
|
name: rake
|
|
59
87
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -180,6 +208,34 @@ dependencies:
|
|
|
180
208
|
- - ">="
|
|
181
209
|
- !ruby/object:Gem::Version
|
|
182
210
|
version: '0'
|
|
211
|
+
- !ruby/object:Gem::Dependency
|
|
212
|
+
name: nokogiri
|
|
213
|
+
requirement: !ruby/object:Gem::Requirement
|
|
214
|
+
requirements:
|
|
215
|
+
- - "<"
|
|
216
|
+
- !ruby/object:Gem::Version
|
|
217
|
+
version: '1.7'
|
|
218
|
+
type: :development
|
|
219
|
+
prerelease: false
|
|
220
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
221
|
+
requirements:
|
|
222
|
+
- - "<"
|
|
223
|
+
- !ruby/object:Gem::Version
|
|
224
|
+
version: '1.7'
|
|
225
|
+
- !ruby/object:Gem::Dependency
|
|
226
|
+
name: rubocop
|
|
227
|
+
requirement: !ruby/object:Gem::Requirement
|
|
228
|
+
requirements:
|
|
229
|
+
- - ">="
|
|
230
|
+
- !ruby/object:Gem::Version
|
|
231
|
+
version: '0'
|
|
232
|
+
type: :development
|
|
233
|
+
prerelease: false
|
|
234
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
235
|
+
requirements:
|
|
236
|
+
- - ">="
|
|
237
|
+
- !ruby/object:Gem::Version
|
|
238
|
+
version: '0'
|
|
183
239
|
- !ruby/object:Gem::Dependency
|
|
184
240
|
name: sqlite3
|
|
185
241
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -236,6 +292,7 @@ files:
|
|
|
236
292
|
- gemfiles/opal_0.9_react_13.gemfile
|
|
237
293
|
- gemfiles/opal_0.9_react_14.gemfile
|
|
238
294
|
- gemfiles/opal_0.9_react_15.gemfile
|
|
295
|
+
- gemfiles/opal_master_react_15.gemfile
|
|
239
296
|
- hyper-react.gemspec
|
|
240
297
|
- lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb
|
|
241
298
|
- lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb
|
|
@@ -261,6 +318,9 @@ files:
|
|
|
261
318
|
- lib/react/component/props_wrapper.rb
|
|
262
319
|
- lib/react/component/should_component_update.rb
|
|
263
320
|
- lib/react/component/tags.rb
|
|
321
|
+
- lib/react/config.rb
|
|
322
|
+
- lib/react/config/client.rb.erb
|
|
323
|
+
- lib/react/config/server.rb
|
|
264
324
|
- lib/react/element.rb
|
|
265
325
|
- lib/react/event.rb
|
|
266
326
|
- lib/react/ext/hash.rb
|
|
@@ -269,10 +329,13 @@ files:
|
|
|
269
329
|
- lib/react/hash.rb
|
|
270
330
|
- lib/react/native_library.rb
|
|
271
331
|
- lib/react/object.rb
|
|
272
|
-
- lib/react/
|
|
332
|
+
- lib/react/react-source-browser.rb
|
|
333
|
+
- lib/react/react-source-server.rb
|
|
273
334
|
- lib/react/react-source.rb
|
|
335
|
+
- lib/react/ref_callback.rb
|
|
274
336
|
- lib/react/rendering_context.rb
|
|
275
|
-
- lib/react/
|
|
337
|
+
- lib/react/server.rb
|
|
338
|
+
- lib/react/state_wrapper.rb
|
|
276
339
|
- lib/react/test.rb
|
|
277
340
|
- lib/react/test/dsl.rb
|
|
278
341
|
- lib/react/test/matchers/render_html_matcher.rb
|
|
@@ -294,10 +357,6 @@ files:
|
|
|
294
357
|
- lib/reactrb/auto-import.rb
|
|
295
358
|
- lib/reactrb/deep-compare.rb
|
|
296
359
|
- lib/reactrb/new-event-name-convention.rb
|
|
297
|
-
- lib/sources/react-latest.js
|
|
298
|
-
- lib/sources/react-v13.js
|
|
299
|
-
- lib/sources/react-v14.js
|
|
300
|
-
- lib/sources/react-v15.js
|
|
301
360
|
- logo1.png
|
|
302
361
|
- logo2.png
|
|
303
362
|
- logo3.png
|
|
@@ -316,6 +375,8 @@ files:
|
|
|
316
375
|
- spec/react/opal_jquery_extensions_spec.rb
|
|
317
376
|
- spec/react/param_declaration_spec.rb
|
|
318
377
|
- spec/react/react_spec.rb
|
|
378
|
+
- spec/react/refs_callback_spec.rb
|
|
379
|
+
- spec/react/server_spec.rb
|
|
319
380
|
- spec/react/state_spec.rb
|
|
320
381
|
- spec/react/test/dsl_spec.rb
|
|
321
382
|
- spec/react/test/matchers/render_html_matcher_spec.rb
|
|
@@ -354,7 +415,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
354
415
|
version: '0'
|
|
355
416
|
requirements: []
|
|
356
417
|
rubyforge_project:
|
|
357
|
-
rubygems_version: 2.
|
|
418
|
+
rubygems_version: 2.5.1
|
|
358
419
|
signing_key:
|
|
359
420
|
specification_version: 4
|
|
360
421
|
summary: Opal Ruby wrapper of React.js library.
|
|
@@ -373,6 +434,8 @@ test_files:
|
|
|
373
434
|
- spec/react/opal_jquery_extensions_spec.rb
|
|
374
435
|
- spec/react/param_declaration_spec.rb
|
|
375
436
|
- spec/react/react_spec.rb
|
|
437
|
+
- spec/react/refs_callback_spec.rb
|
|
438
|
+
- spec/react/server_spec.rb
|
|
376
439
|
- spec/react/state_spec.rb
|
|
377
440
|
- spec/react/test/dsl_spec.rb
|
|
378
441
|
- spec/react/test/matchers/render_html_matcher_spec.rb
|
data/lib/react/observable.rb
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module React
|
|
2
|
-
class Observable
|
|
3
|
-
def initialize(value, on_change = nil, &block)
|
|
4
|
-
@value = value
|
|
5
|
-
@on_change = on_change || block
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def method_missing(method_sym, *args, &block)
|
|
9
|
-
@value.send(method_sym, *args, &block).tap { |result| @on_change.call @value }
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def respond_to?(method, *args)
|
|
13
|
-
if [:call, :to_proc].include? method
|
|
14
|
-
true
|
|
15
|
-
else
|
|
16
|
-
@value.respond_to? method, *args
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def call(new_value)
|
|
21
|
-
@on_change.call new_value
|
|
22
|
-
@value = new_value
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def to_proc
|
|
26
|
-
lambda { |arg = @value| @on_change.call arg }
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
data/lib/react/state.rb
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
module React
|
|
2
|
-
class StateWrapper < BasicObject
|
|
3
|
-
def initialize(native, from)
|
|
4
|
-
@state_hash = Hash.new(`#{native}.state`)
|
|
5
|
-
@from = from
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def [](state)
|
|
9
|
-
@state_hash[state]
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def []=(state, new_value)
|
|
13
|
-
@state_hash[state] = new_value
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def method_missing(method, *args)
|
|
17
|
-
if match = method.match(/^(.+)\!$/)
|
|
18
|
-
key_name = $1
|
|
19
|
-
if args.count > 0
|
|
20
|
-
current_value = State.get_state(@from, match[1])
|
|
21
|
-
State.set_state(@from, key_name, args[0])
|
|
22
|
-
current_value
|
|
23
|
-
else
|
|
24
|
-
current_state = State.get_state(@from, match[1])
|
|
25
|
-
State.set_state(@from, key_name, current_state)
|
|
26
|
-
Observable.new(current_state) do |update|
|
|
27
|
-
State.set_state(@from, key_name, update)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
else
|
|
31
|
-
State.get_state(@from, method)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
class State
|
|
37
|
-
|
|
38
|
-
@rendering_level = 0
|
|
39
|
-
|
|
40
|
-
class << self
|
|
41
|
-
attr_reader :current_observer
|
|
42
|
-
|
|
43
|
-
def has_observers?(object, name)
|
|
44
|
-
!observers_by_name[object][name].empty?
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def bulk_update
|
|
48
|
-
saved_bulk_update_flag = @bulk_update_flag
|
|
49
|
-
@bulk_update_flag = true
|
|
50
|
-
yield
|
|
51
|
-
ensure
|
|
52
|
-
@bulk_update_flag = saved_bulk_update_flag
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def set_state2(object, name, value, updates, exclusions = nil)
|
|
56
|
-
# set object's name state to value, tell all observers it has changed.
|
|
57
|
-
# Observers must implement update_react_js_state
|
|
58
|
-
object_needs_notification = object.respond_to? :update_react_js_state
|
|
59
|
-
observers_by_name[object][name].dup.each do |observer|
|
|
60
|
-
next if exclusions && exclusions.include?(observer)
|
|
61
|
-
updates[observer] += [object, name, value]
|
|
62
|
-
object_needs_notification = false if object == observer
|
|
63
|
-
end
|
|
64
|
-
updates[object] += [nil, name, value] if object_needs_notification
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def initialize_states(object, initial_values) # initialize objects' name/value pairs
|
|
68
|
-
states[object].merge!(initial_values || {})
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def get_state(object, name, current_observer = @current_observer)
|
|
72
|
-
# get current value of name for object, remember that the current object depends on this state,
|
|
73
|
-
# current observer can be overriden with last param
|
|
74
|
-
if current_observer && !new_observers[current_observer][object].include?(name)
|
|
75
|
-
new_observers[current_observer][object] << name
|
|
76
|
-
end
|
|
77
|
-
if @delayed_updates && @delayed_updates[object][name]
|
|
78
|
-
@delayed_updates[object][name][1] << current_observer
|
|
79
|
-
end
|
|
80
|
-
states[object][name]
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def set_state(object, name, value, delay=nil)
|
|
84
|
-
states[object][name] = value
|
|
85
|
-
if delay || @bulk_update_flag
|
|
86
|
-
@delayed_updates ||= Hash.new { |h, k| h[k] = {} }
|
|
87
|
-
@delayed_updates[object][name] = [value, Set.new]
|
|
88
|
-
@delayed_updater ||= after(0.001) do
|
|
89
|
-
delayed_updates = @delayed_updates
|
|
90
|
-
@delayed_updates = Hash.new { |h, k| h[k] = {} } # could this be nil???
|
|
91
|
-
@delayed_updater = nil
|
|
92
|
-
updates = Hash.new { |hash, key| hash[key] = Array.new }
|
|
93
|
-
delayed_updates.each do |object, name_hash|
|
|
94
|
-
name_hash.each do |name, value_and_set|
|
|
95
|
-
set_state2(object, name, value_and_set[0], updates, value_and_set[1])
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
updates.each { |observer, args| observer.update_react_js_state(*args) }
|
|
99
|
-
end
|
|
100
|
-
elsif @rendering_level == 0
|
|
101
|
-
updates = Hash.new { |hash, key| hash[key] = Array.new }
|
|
102
|
-
set_state2(object, name, value, updates)
|
|
103
|
-
updates.each { |observer, args| observer.update_react_js_state(*args) }
|
|
104
|
-
end
|
|
105
|
-
value
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def notify_observers(object, name, value)
|
|
109
|
-
object_needs_notification = object.respond_to? :update_react_js_state
|
|
110
|
-
observers_by_name[object][name].dup.each do |observer|
|
|
111
|
-
observer.update_react_js_state(object, name, value)
|
|
112
|
-
object_needs_notification = false if object == observer
|
|
113
|
-
end
|
|
114
|
-
object.update_react_js_state(nil, name, value) if object_needs_notification
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def notify_observers_after_thread_completes(object, name, value)
|
|
118
|
-
(@delayed_updates ||= []) << [object, name, value]
|
|
119
|
-
@delayed_updater ||= after(0) do
|
|
120
|
-
delayed_updates = @delayed_updates
|
|
121
|
-
@delayed_updates = []
|
|
122
|
-
@delayed_updater = nil
|
|
123
|
-
delayed_updates.each { |args| notify_observers(*args) }
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def will_be_observing?(object, name, current_observer)
|
|
128
|
-
current_observer && new_observers[current_observer][object].include?(name)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def is_observing?(object, name, current_observer)
|
|
132
|
-
current_observer && observers_by_name[object][name].include?(current_observer)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def update_states_to_observe(current_observer = @current_observer) # should be called after the last after_render callback, currently called after components render method
|
|
136
|
-
raise "update_states_to_observer called outside of watch block" unless current_observer
|
|
137
|
-
current_observers[current_observer].each do |object, names|
|
|
138
|
-
names.each do |name|
|
|
139
|
-
observers_by_name[object][name].delete(current_observer)
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
observers = current_observers[current_observer] = new_observers[current_observer]
|
|
143
|
-
new_observers.delete(current_observer)
|
|
144
|
-
observers.each do |object, names|
|
|
145
|
-
names.each do |name|
|
|
146
|
-
observers_by_name[object][name] << current_observer
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def remove # call after component is unmounted
|
|
152
|
-
raise "remove called outside of watch block" unless @current_observer
|
|
153
|
-
current_observers[@current_observer].each do |object, names|
|
|
154
|
-
names.each do |name|
|
|
155
|
-
observers_by_name[object][name].delete(@current_observer)
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
current_observers.delete(@current_observer)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def set_state_context_to(observer, rendering = nil) # wrap all execution that may set or get states in a block so we know which observer is executing
|
|
162
|
-
if `typeof Opal.global.reactive_ruby_timing !== 'undefined'`
|
|
163
|
-
@nesting_level = (@nesting_level || 0) + 1
|
|
164
|
-
start_time = Time.now.to_f
|
|
165
|
-
observer_name = (observer.class.respond_to?(:name) ? observer.class.name : observer.to_s) rescue "object:#{observer.object_id}"
|
|
166
|
-
end
|
|
167
|
-
saved_current_observer = @current_observer
|
|
168
|
-
@current_observer = observer
|
|
169
|
-
@rendering_level += 1 if rendering
|
|
170
|
-
return_value = yield
|
|
171
|
-
return_value
|
|
172
|
-
ensure
|
|
173
|
-
@current_observer = saved_current_observer
|
|
174
|
-
@rendering_level -= 1 if rendering
|
|
175
|
-
@nesting_level = [0, @nesting_level - 1].max if `typeof Opal.global.reactive_ruby_timing !== 'undefined'`
|
|
176
|
-
return_value
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
def states
|
|
180
|
-
@states ||= Hash.new { |h, k| h[k] = {} }
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
[:new_observers, :current_observers, :observers_by_name].each do |method_name|
|
|
184
|
-
define_method(method_name) do
|
|
185
|
-
instance_variable_get("@#{method_name}") ||
|
|
186
|
-
instance_variable_set("@#{method_name}", Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = [] } })
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
end
|