hyper-router 1.0.alpha1.8 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +22 -0
- data/README.md +393 -0
- data/Rakefile +27 -6
- data/lib/hyper-router.rb +13 -22
- data/lib/patches/react.rb +9 -0
- data/lib/promise_extras.rb +7 -0
- data/lib/react/router.rb +117 -2
- data/lib/react/router/dsl.rb +31 -0
- data/lib/react/router/dsl/index.rb +11 -0
- data/lib/react/router/dsl/route.rb +89 -0
- data/lib/react/router/dsl/route/hooks.rb +21 -0
- data/lib/react/router/dsl/route/wrappers.rb +104 -0
- data/lib/react/router/dsl/transition_context.rb +27 -0
- data/lib/react/router/react-router.js +2 -0
- data/lib/react/router/version.rb +3 -0
- metadata +172 -92
- data/lib/hyperstack/internal/router/class_methods.rb +0 -33
- data/lib/hyperstack/internal/router/helpers.rb +0 -74
- data/lib/hyperstack/internal/router/instance_methods.rb +0 -15
- data/lib/hyperstack/internal/router/isomorphic_methods.rb +0 -26
- data/lib/hyperstack/router.rb +0 -76
- data/lib/hyperstack/router/helpers.rb +0 -27
- data/lib/hyperstack/router/history.rb +0 -48
- data/lib/hyperstack/router/location.rb +0 -31
- data/lib/hyperstack/router/match.rb +0 -20
- data/lib/hyperstack/router/react-router-source.rb +0 -4
- data/lib/hyperstack/router/version.rb +0 -3
- data/lib/react/router/dom.rb +0 -7
- data/lib/react/router/history.rb +0 -25
- data/lib/src/history.min.js +0 -1
- data/lib/src/react-router-dom.min.js +0 -1
- data/lib/src/react-router.min.js +0 -1
data/lib/hyper-router.rb
CHANGED
@@ -1,29 +1,20 @@
|
|
1
|
-
# rubocop:disable Style/FileName
|
2
|
-
|
3
|
-
require 'hyper-component'
|
4
|
-
|
5
|
-
Hyperstack.js_import 'hyperstack/router/react-router-source', defines: ['ReactRouter', 'ReactRouterDOM', 'History']
|
6
|
-
Hyperstack.import 'hyper-router'
|
7
|
-
|
8
1
|
if RUBY_ENGINE == 'opal'
|
2
|
+
# require 'reactrb' # how to require this conditionally????
|
3
|
+
require 'hyper-react'
|
4
|
+
require 'promise'
|
5
|
+
require 'promise_extras'
|
6
|
+
require 'react/router/react-router'
|
9
7
|
require 'react/router'
|
10
|
-
require 'react/router/
|
11
|
-
require 'react/router/
|
12
|
-
|
13
|
-
require '
|
14
|
-
require '
|
15
|
-
require 'hyperstack/router/location'
|
16
|
-
require 'hyperstack/router/match'
|
17
|
-
require 'hyperstack/internal/router/class_methods'
|
18
|
-
require 'hyperstack/internal/router/helpers'
|
19
|
-
require 'hyperstack/internal/router/instance_methods'
|
20
|
-
|
21
|
-
require 'hyperstack/router/helpers'
|
22
|
-
require 'hyperstack/router'
|
8
|
+
require 'react/router/dsl'
|
9
|
+
require 'react/router/dsl/route'
|
10
|
+
require 'react/router/dsl/index'
|
11
|
+
require 'react/router/dsl/transition_context'
|
12
|
+
require 'patches/react'
|
23
13
|
else
|
24
14
|
require 'opal'
|
25
|
-
require '
|
26
|
-
require '
|
15
|
+
require 'hyper-react'
|
16
|
+
require 'react/router/version'
|
27
17
|
|
28
18
|
Opal.append_path File.expand_path('../', __FILE__).untaint
|
19
|
+
Opal.append_path File.expand_path('../../vendor', __FILE__).untaint
|
29
20
|
end
|
data/lib/react/router.rb
CHANGED
@@ -1,5 +1,120 @@
|
|
1
1
|
module React
|
2
|
-
class Router
|
3
|
-
|
2
|
+
class Router
|
3
|
+
include React::Component
|
4
|
+
|
5
|
+
def self.Link(to, opts = {}, &children)
|
6
|
+
opts[:activeClassName] = opts.delete(:active_class).to_n if opts[:active_class]
|
7
|
+
opts[:activeStyle] = opts.delete(:active_style).to_n if opts[:active_style]
|
8
|
+
if opts[:only_active_on_index]
|
9
|
+
opts[:onlyActiveOnIndex] = opts.delete(:only_active_on_index).to_n
|
10
|
+
end
|
11
|
+
opts[:to] = to.to_n
|
12
|
+
Native::Link(opts, &children)
|
13
|
+
end
|
14
|
+
|
15
|
+
def route(*args, &children)
|
16
|
+
DSL::Route.new(*args, &children)
|
17
|
+
end
|
18
|
+
|
19
|
+
def index(opts = {})
|
20
|
+
DSL::Index.new(opts)
|
21
|
+
end
|
22
|
+
|
23
|
+
def redirect(from, opts = {})
|
24
|
+
DSL::Route.new(opts.merge(path: from)).on(:enter) { |c| c.replace(opts[:to]) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def index_redirect(opts = {})
|
28
|
+
DSL::Index.new(opts).on(:enter) { |c| c.replace(opts[:to]) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_routes(&block)
|
32
|
+
React::Router::DSL.build_routes(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def hash_history
|
36
|
+
`window.ReactRouter.hashHistory`
|
37
|
+
end
|
38
|
+
|
39
|
+
def browser_history
|
40
|
+
`window.ReactRouter.browserHistory`
|
41
|
+
end
|
42
|
+
|
43
|
+
def gather_params
|
44
|
+
params = { routes: React::Router::DSL.children_to_n(build_routes { routes }) }
|
45
|
+
params[:history] = history if respond_to? :history
|
46
|
+
%w(create_element stringify_query parse_query_string on_error on_update).each do |method|
|
47
|
+
params[method.camelcase(false)] = send("#{method}_wrapper") if respond_to? method
|
48
|
+
end
|
49
|
+
params
|
50
|
+
end
|
51
|
+
|
52
|
+
def render
|
53
|
+
Native::Router(gather_params)
|
54
|
+
end
|
55
|
+
|
56
|
+
# private
|
57
|
+
|
58
|
+
class Native < React::NativeLibrary
|
59
|
+
imports "ReactRouter"
|
60
|
+
end
|
61
|
+
|
62
|
+
def stringify_query_wrapper
|
63
|
+
->(query) { stringify_query(query) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_query_string_wrapper
|
67
|
+
->(query_string) { parse_query_string(query_string) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def on_update_wrapper
|
71
|
+
-> { on_update(Hash.new(`this.props`), Hash.new(`this.state`)) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_element_wrapper
|
75
|
+
lambda do |component, props|
|
76
|
+
comp_classes = React::API.class_eval { @@component_classes }
|
77
|
+
rb_component = comp_classes.detect { |_key, value| value == component }.first
|
78
|
+
# Not sure if this could ever happen,
|
79
|
+
# could not figure out a way to test it so commented it out.
|
80
|
+
# unless rb_component
|
81
|
+
# rb_component = Class.new(React::Component::Base)
|
82
|
+
# comp_classes[rb_component] = component
|
83
|
+
# end
|
84
|
+
rb_props = convert_props(props)
|
85
|
+
result = create_element(rb_component, rb_props)
|
86
|
+
convert_or_create_element(result, component, props, rb_component, rb_props)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def on_error_wrapper
|
91
|
+
-> (message) { on_error(message) }
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def convert_props(props)
|
97
|
+
children_are_null = `props.children == undefined || props.children == null`
|
98
|
+
{ children: children_are_null ? [] : [`props.children`].flatten,
|
99
|
+
history: `props.history`,
|
100
|
+
location: `props.location`,
|
101
|
+
params: `props.params`,
|
102
|
+
route: `props.route`,
|
103
|
+
route_params: `props.route_params`,
|
104
|
+
routes: `props.routes` }
|
105
|
+
end
|
106
|
+
|
107
|
+
def convert_or_create_element(result, component, props, rb_component, rb_props)
|
108
|
+
is_result_native_react_element = `!!result._isReactElement`
|
109
|
+
if is_result_native_react_element
|
110
|
+
result
|
111
|
+
elsif !result
|
112
|
+
`React.createElement(component, props)`
|
113
|
+
elsif result.is_a? React::Element
|
114
|
+
result.to_n
|
115
|
+
else
|
116
|
+
React.create_element(rb_component, rb_props).to_n
|
117
|
+
end
|
118
|
+
end
|
4
119
|
end
|
5
120
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module React
|
2
|
+
class Router
|
3
|
+
class DSL
|
4
|
+
def self.build_routes(*args, &block)
|
5
|
+
evaluate_children(*args, &block)[0]
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.evaluate_children(*args, &children)
|
9
|
+
[[], nil].tap do |new_routes|
|
10
|
+
if children
|
11
|
+
saved_routes, @routes = [@routes, new_routes]
|
12
|
+
@routes << children.call(*args)
|
13
|
+
@routes = saved_routes
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.add_element(element)
|
19
|
+
@routes[0] << element
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.set_index(index)
|
23
|
+
@routes[1] = index
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.children_to_n(children)
|
27
|
+
children.collect { |e| e.to_json.to_n }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'react/router/dsl/route/hooks'
|
2
|
+
require 'react/router/dsl/route/wrappers'
|
3
|
+
|
4
|
+
module React
|
5
|
+
class Router
|
6
|
+
class DSL
|
7
|
+
class Route
|
8
|
+
def initialize(*args, &children)
|
9
|
+
path =
|
10
|
+
if args[0].is_a? Hash
|
11
|
+
nil
|
12
|
+
else
|
13
|
+
args[0]
|
14
|
+
end
|
15
|
+
opts =
|
16
|
+
if args[0].is_a? Hash
|
17
|
+
args[0]
|
18
|
+
else
|
19
|
+
args[1] || {}
|
20
|
+
end
|
21
|
+
unless opts.is_a? Hash
|
22
|
+
raise 'Route expects an optional path followed by an options hash, '\
|
23
|
+
"instead we got route(#{'"' + path + '", ' if path} #{opts})"
|
24
|
+
end
|
25
|
+
@children, @index = DSL.evaluate_children do
|
26
|
+
yield if children && children.arity == 0
|
27
|
+
Index.new(mounts: opts[:index]) if opts[:index]
|
28
|
+
end
|
29
|
+
opts.delete(:index)
|
30
|
+
@get_children = children if children && children.arity > 0
|
31
|
+
@path = path
|
32
|
+
if opts[:mounts].is_a? Hash
|
33
|
+
@components = opts[:mounts]
|
34
|
+
else
|
35
|
+
@component = opts[:mounts]
|
36
|
+
end
|
37
|
+
opts.delete(:mounts)
|
38
|
+
@opts = opts
|
39
|
+
save_element
|
40
|
+
end
|
41
|
+
|
42
|
+
def save_element
|
43
|
+
DSL.add_element(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json
|
47
|
+
hash = {}
|
48
|
+
hash[:path] = @path if @path
|
49
|
+
|
50
|
+
if @get_children
|
51
|
+
hash[:getChildRoutes] = get_child_routes_wrapper
|
52
|
+
else
|
53
|
+
hash[:childRoutes] = @children.map(&:to_json)
|
54
|
+
end
|
55
|
+
|
56
|
+
if @components
|
57
|
+
if @components.detect { |_k, v| v.respond_to? :call }
|
58
|
+
hash[:getComponents] = get_components_wrapper
|
59
|
+
else
|
60
|
+
hash[:components] = @components
|
61
|
+
end
|
62
|
+
elsif @component.respond_to? :call
|
63
|
+
hash[:getComponent] = get_component_wrapper
|
64
|
+
elsif @component
|
65
|
+
hash[:component] = React::API.create_native_react_class(@component)
|
66
|
+
else
|
67
|
+
hash[:component] = DSL.router.lookup_component(@path)
|
68
|
+
end
|
69
|
+
|
70
|
+
%w(enter change leave).each do |hook|
|
71
|
+
hash["on#{hook.camelcase}"] = send("on_#{hook}_wrapper") if @opts["on_#{hook}"]
|
72
|
+
end
|
73
|
+
|
74
|
+
if @index.respond_to? :call
|
75
|
+
hash[:getIndexRoute] = get_index_route_wrapper
|
76
|
+
elsif @index
|
77
|
+
hash[:indexRoute] = @index.to_json
|
78
|
+
end
|
79
|
+
|
80
|
+
@opts.each do |key, value|
|
81
|
+
hash[key] = value unless %w(on_enter on_change on_leave).include?(key)
|
82
|
+
end
|
83
|
+
|
84
|
+
hash
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module React
|
2
|
+
class Router
|
3
|
+
class DSL
|
4
|
+
class Route
|
5
|
+
def on(hook, &block)
|
6
|
+
@opts["on_#{hook}"] = block
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
def mounts(name = nil, &block)
|
11
|
+
if name
|
12
|
+
@components ||= {}
|
13
|
+
@components[name] = block
|
14
|
+
else
|
15
|
+
@component = block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module React
|
2
|
+
class Router
|
3
|
+
class DSL
|
4
|
+
class Route
|
5
|
+
def get_child_routes_wrapper
|
6
|
+
lambda do |location, callBack|
|
7
|
+
children, index, promise =
|
8
|
+
React::Router::DSL.evaluate_children(TransitionContext.new(location: location),
|
9
|
+
&@get_children)
|
10
|
+
if promise.class < Promise || promise.is_a?(Promise)
|
11
|
+
|
12
|
+
promise.then do |children|
|
13
|
+
callBack.call(nil.to_n, React::Router::DSL.children_to_n(children))
|
14
|
+
end.fail { |err_object| callBack.call(err_object, nil.to_n) }
|
15
|
+
else
|
16
|
+
callBack.call(nil.to_n, DSL.children_to_n(children))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
def get_components_wrapper
|
21
|
+
lambda do |nextState, callBack|
|
22
|
+
result_hash = {}
|
23
|
+
promises = []
|
24
|
+
@components.each do |name, proc_or_comp|
|
25
|
+
if proc_or_comp.respond_to? :call
|
26
|
+
comp = proc.call(TransitionContext.new(next_state: nextState))
|
27
|
+
if comp.class < Promise || comp.is_a?(Promise)
|
28
|
+
promises << comp
|
29
|
+
comp.then do |component|
|
30
|
+
result_hash[name] = React::API.create_native_react_class(component)
|
31
|
+
end.fail { |err_object| `callBack(#{err_object}, null)` }
|
32
|
+
else
|
33
|
+
result_hash[name] = React::API.create_native_react_class(comp)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
result_hash[name] = React::API.create_native_react_class(proc_or_comp)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
Promise.when(*promises).then { `callBack(null, #{result_hash.to_n})` }
|
40
|
+
end.to_n
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_component_wrapper
|
44
|
+
lambda do |nextState, callBack|
|
45
|
+
comp = @component.call(TransitionContext.new(next_state: nextState))
|
46
|
+
if comp.class < Promise || comp.is_a?(Promise)
|
47
|
+
comp.then do |component|
|
48
|
+
component = React::API.create_native_react_class(component)
|
49
|
+
`callBack(null, component)`
|
50
|
+
end.fail { |err_object| `callBack(#{err_object}, null)` }
|
51
|
+
else
|
52
|
+
comp = React::API.create_native_react_class(comp)
|
53
|
+
`callBack(null, comp)`
|
54
|
+
end
|
55
|
+
end.to_n
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_enter_wrapper
|
59
|
+
lambda do |nextState, replace, callBack|
|
60
|
+
comp =
|
61
|
+
@opts[:on_enter].call(TransitionContext.new(next_state: nextState,
|
62
|
+
replace: replace))
|
63
|
+
if comp.class < Promise || comp.is_a?(Promise)
|
64
|
+
comp.then { `callBack()` }
|
65
|
+
else
|
66
|
+
`callBack()`
|
67
|
+
end
|
68
|
+
end.to_n
|
69
|
+
end
|
70
|
+
|
71
|
+
def on_change_wrapper(proc)
|
72
|
+
lambda do |prevState, nextState, replace, callBack|
|
73
|
+
comp = @opts[:on_change].call(TransitionContext.new(prev_state: prevState,
|
74
|
+
next_state: nextState,
|
75
|
+
replace: replace))
|
76
|
+
if comp.class < Promise || comp.is_a?(Promise)
|
77
|
+
comp.then { `callBack()` }
|
78
|
+
else
|
79
|
+
`callBack()`
|
80
|
+
end
|
81
|
+
end.to_n
|
82
|
+
end
|
83
|
+
|
84
|
+
def on_leave_wrapper(proc)
|
85
|
+
lambda do
|
86
|
+
@opts[:on_leave].call(TransitionContext.new)
|
87
|
+
end.to_n
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_index_route_wrapper
|
91
|
+
lambda do |location, callBack|
|
92
|
+
comp = @opts[:index].call(TransitionContext.new(location: location))
|
93
|
+
if comp.class < Promise || comp.is_a?(Promise)
|
94
|
+
comp.then { |component| `callBack(null, {component: #{component}})` }
|
95
|
+
.fail { |err_object| `callBack(#{err_object}, null)` }
|
96
|
+
else
|
97
|
+
`callBack(null, {component: #{comp}})`
|
98
|
+
end
|
99
|
+
end.to_n
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|