view_component_reflex 3.0.6.pre.1 → 3.1.4

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.
@@ -1,189 +1,200 @@
1
- module ViewComponentReflex
2
- class Reflex < StimulusReflex::Reflex
3
-
4
- class << self
5
- attr_accessor :component_class
6
- end
7
-
8
- def refresh!(primary_selector = nil, *rest)
9
- save_state
10
-
11
- if primary_selector.nil? && !component.can_render_to_string?
12
- primary_selector = selector
13
- end
14
- if primary_selector
15
- prevent_refresh!
16
-
17
- controller.process(params[:action])
18
- document = Nokogiri::HTML(controller.response.body)
19
- [primary_selector, *rest].each do |s|
20
- html = document.css(s)
21
- if html.present?
22
- CableReady::Channels.instance[stream_name].morph(
23
- selector: s,
24
- html: html.inner_html,
25
- children_only: true,
26
- permanent_attribute_name: "data-reflex-permanent",
27
- stimulus_reflex: stimulus_reflex_data
28
- )
29
- end
30
- end
31
- else
32
- refresh_component!
33
- end
34
- cable_ready.broadcast
35
- end
36
-
37
- def refresh_component!
38
- component.tap do |k|
39
- k.define_singleton_method(:key) do
40
- element.dataset[:key]
41
- end
42
- end
43
- document = Nokogiri::HTML(component.render_in(controller.view_context))
44
- CableReady::Channels.instance[stream_name].morph(
45
- selector: selector,
46
- children_only: true,
47
- html: document.css(selector).inner_html,
48
- permanent_attribute_name: "data-reflex-permanent",
49
- stimulus_reflex: stimulus_reflex_data
50
- )
51
- end
52
-
53
- def stimulus_reflex_data
54
- {
55
- reflex_id: reflex_id,
56
- xpath: xpath,
57
- target: target,
58
- c_xpath: c_xpath,
59
- reflex_controller: reflex_controller,
60
- url: url,
61
- morph: :page,
62
- attrs: {
63
- key: element.dataset[:key]
64
- }
65
- }
66
- end
67
-
68
- def target
69
- "#{component_class}##{method_name}"
70
- end
71
-
72
- def refresh_all!
73
- refresh!("body")
74
- end
75
-
76
- def selector
77
- "[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]"
78
- end
79
-
80
- # SR's delegate_call_to_reflex in channel.rb
81
- # uses method to gather the method parameters, but since we're abusing
82
- # method_missing here, that'll always fail
83
- def method(name)
84
- component.method(name.to_sym)
85
- end
86
-
87
- def respond_to_missing?(name, _ = false)
88
- !!name.to_proc
89
- end
90
-
91
- # this is copied out of stimulus_reflex/reflex.rb and modified
92
- def morph(selectors, html = "")
93
- case selectors
94
- when :nothing
95
- @broadcaster = StimulusReflex::NothingBroadcaster.new(self)
96
- else
97
- @broadcaster = StimulusReflex::SelectorBroadcaster.new(self) unless broadcaster.selector?
98
- broadcaster.morphs << [selectors, html]
99
- end
100
- end
101
-
102
- def method_missing(name, *args)
103
- morph :nothing
104
- super unless respond_to_missing?(name)
105
- state.each do |k, v|
106
- component.instance_variable_set(k, v)
107
- end
108
- name.to_proc.call(component, *args)
109
- refresh! unless @prevent_refresh
110
- end
111
-
112
- def prevent_refresh!
113
- @prevent_refresh = true
114
- end
115
-
116
- private
117
-
118
- def component_class
119
- self.class.component_class
120
- end
121
-
122
- def stimulus_controller
123
- component_class.stimulus_controller
124
- end
125
-
126
- def stimulate(target, data)
127
- data_to_receive = {}
128
-
129
- stimulus_reflex_data.each do |k, v|
130
- data_to_receive[k.to_s.camelize(:lower)] = v
131
- end
132
-
133
- data_to_receive["dataset"] = data.each_with_object({}) do |(k, v), o|
134
- o["data-#{k}"] = v
135
- end
136
-
137
- data_to_receive["attrs"] = element.attributes.to_h.symbolize_keys
138
- data_to_receive["target"] = target
139
-
140
- channel.receive data_to_receive
141
- end
142
-
143
- def component
144
- return @component if @component
145
- @component = component_class.allocate
146
- reflex = self
147
- exposed_methods = [
148
- :params,
149
- :request,
150
- :connection,
151
- :element,
152
- :refresh!,
153
- :refresh_all!,
154
- :stimulus_controller,
155
- :session,
156
- :prevent_refresh!,
157
- :selector,
158
- :stimulate
159
- ]
160
- exposed_methods.each do |meth|
161
- @component.define_singleton_method(meth) do |*a|
162
- reflex.send(meth, *a)
163
- end
164
- end
165
-
166
- @component.define_singleton_method(:reflex) do
167
- reflex
168
- end
169
-
170
- @component
171
- end
172
-
173
- def set_state(new_state = {})
174
- ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
175
- end
176
-
177
- def state
178
- ViewComponentReflex::Engine.state_adapter.state(request, element.dataset[:key])
179
- end
180
-
181
- def save_state
182
- new_state = {}
183
- component.safe_instance_variables.each do |k|
184
- new_state[k] = component.instance_variable_get(k)
185
- end
186
- set_state(new_state)
187
- end
188
- end
189
- end
1
+ module ViewComponentReflex
2
+ class Reflex < StimulusReflex::Reflex
3
+
4
+ class << self
5
+ attr_accessor :component_class
6
+ end
7
+
8
+ def refresh!(primary_selector = nil, *rest)
9
+ save_state
10
+
11
+ if primary_selector.nil? && !component.can_render_to_string?
12
+ primary_selector = selector
13
+ end
14
+ if primary_selector
15
+ prevent_refresh!
16
+
17
+ controller.process(params[:action])
18
+ document = Nokogiri::HTML(controller.response.body)
19
+ [primary_selector, *rest].each do |s|
20
+ html = document.css(s)
21
+ if html.present?
22
+ CableReady::Channels.instance[stream].morph(
23
+ selector: s,
24
+ html: html.inner_html,
25
+ children_only: true,
26
+ permanent_attribute_name: "data-reflex-permanent",
27
+ stimulus_reflex: stimulus_reflex_data
28
+ )
29
+ end
30
+ end
31
+ else
32
+ refresh_component!
33
+ end
34
+ CableReady::Channels.instance.broadcast
35
+ end
36
+
37
+ def stream
38
+ @stream ||= stream_name
39
+ end
40
+
41
+ def stream_to(channel)
42
+ @stream = channel
43
+ end
44
+
45
+ def refresh_component!
46
+ component.tap do |k|
47
+ k.define_singleton_method(:key) do
48
+ element.dataset[:key]
49
+ end
50
+ end
51
+ document = Nokogiri::HTML(component.render_in(controller.view_context))
52
+ CableReady::Channels.instance[stream].morph(
53
+ selector: selector,
54
+ children_only: true,
55
+ html: document.css(selector).inner_html,
56
+ permanent_attribute_name: "data-reflex-permanent",
57
+ stimulus_reflex: stimulus_reflex_data
58
+ )
59
+ end
60
+
61
+ def stimulus_reflex_data
62
+ {
63
+ reflex_id: reflex_id,
64
+ xpath_controller: xpath_controller,
65
+ xpath_element: xpath_element,
66
+ target: target,
67
+ reflex_controller: reflex_controller,
68
+ url: url,
69
+ morph: :page,
70
+ attrs: {
71
+ key: element.dataset[:key]
72
+ }
73
+ }
74
+ end
75
+
76
+ def target
77
+ "#{component_class}##{method_name}"
78
+ end
79
+
80
+ def refresh_all!
81
+ refresh!("body")
82
+ end
83
+
84
+ def selector
85
+ "[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]"
86
+ end
87
+
88
+ # SR's delegate_call_to_reflex in channel.rb
89
+ # uses method to gather the method parameters, but since we're abusing
90
+ # method_missing here, that'll always fail
91
+ def method(name)
92
+ component.method(name.to_sym)
93
+ end
94
+
95
+ def respond_to_missing?(name, _ = false)
96
+ !!name.to_proc
97
+ end
98
+
99
+ # this is copied out of stimulus_reflex/reflex.rb and modified
100
+ def morph(selectors, html = "")
101
+ case selectors
102
+ when :nothing
103
+ @broadcaster = StimulusReflex::NothingBroadcaster.new(self)
104
+ else
105
+ @broadcaster = StimulusReflex::SelectorBroadcaster.new(self) unless broadcaster.selector?
106
+ broadcaster.morphs << [selectors, html]
107
+ end
108
+ end
109
+
110
+ def method_missing(name, *args, &blk)
111
+ morph :nothing
112
+ super unless respond_to_missing?(name)
113
+ state.each do |k, v|
114
+ component.instance_variable_set(k, v)
115
+ end
116
+
117
+ component.send(name, *args, &blk)
118
+
119
+ refresh! unless @prevent_refresh
120
+ end
121
+
122
+ def prevent_refresh!
123
+ @prevent_refresh = true
124
+ end
125
+
126
+ private
127
+
128
+ def component_class
129
+ self.class.component_class
130
+ end
131
+
132
+ def stimulus_controller
133
+ component_class.stimulus_controller
134
+ end
135
+
136
+ def stimulate(target, data)
137
+ data_to_receive = {}
138
+
139
+ stimulus_reflex_data.each do |k, v|
140
+ data_to_receive[k.to_s.camelize(:lower)] = v
141
+ end
142
+
143
+ data_to_receive["dataset"] = data.each_with_object({}) do |(k, v), o|
144
+ o["data-#{k}"] = v
145
+ end
146
+
147
+ data_to_receive["attrs"] = element.attributes.to_h.symbolize_keys
148
+ data_to_receive["target"] = target
149
+
150
+ channel.receive data_to_receive
151
+ end
152
+
153
+ def component
154
+ return @component if @component
155
+ @component = component_class.allocate
156
+ reflex = self
157
+ exposed_methods = [
158
+ :params,
159
+ :request,
160
+ :connection,
161
+ :element,
162
+ :refresh!,
163
+ :refresh_all!,
164
+ :stimulus_controller,
165
+ :session,
166
+ :prevent_refresh!,
167
+ :selector,
168
+ :stimulate,
169
+ :stream_to
170
+ ]
171
+ exposed_methods.each do |meth|
172
+ @component.define_singleton_method(meth) do |*a|
173
+ reflex.send(meth, *a)
174
+ end
175
+ end
176
+
177
+ @component.define_singleton_method(:reflex) do
178
+ reflex
179
+ end
180
+
181
+ @component
182
+ end
183
+
184
+ def set_state(new_state = {})
185
+ ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
186
+ end
187
+
188
+ def state
189
+ ViewComponentReflex::Engine.state_adapter.state(request, element.dataset[:key])
190
+ end
191
+
192
+ def save_state
193
+ new_state = {}
194
+ component.safe_instance_variables.each do |k|
195
+ new_state[k] = component.instance_variable_get(k)
196
+ end
197
+ set_state(new_state)
198
+ end
199
+ end
200
+ end
@@ -1,61 +1,61 @@
1
- module ViewComponentReflex
2
- class ReflexFactory
3
- def initialize(component)
4
- @component = component
5
- @new = false
6
- reflex.component_class = component
7
- end
8
-
9
- def nested?
10
- @nested ||= @component.name.include?("::")
11
- end
12
-
13
- def reflex_name
14
- @reflex_name ||= if nested?
15
- @component.name.split("::").last
16
- else
17
- @component.name
18
- end + "Reflex"
19
- end
20
-
21
- def new?
22
- @new
23
- end
24
-
25
- def reflex
26
- @reflex ||= if nested?
27
- reflex_from_nested_component
28
- else
29
- reflex_from_component
30
- end
31
- end
32
-
33
- def reflex_instance
34
- @reflex_instance ||= Class.new(@component.reflex_base_class)
35
- end
36
-
37
- def reflex_from_nested_component
38
- parent = if @component.respond_to? :module_parent
39
- @component.module_parent
40
- else
41
- @component.parent
42
- end
43
-
44
- if parent.const_defined?(reflex_name)
45
- parent.const_get(reflex_name)
46
- else
47
- @new = true
48
- parent.const_set(reflex_name, reflex_instance)
49
- end
50
- end
51
-
52
- def reflex_from_component
53
- if Object.const_defined?(reflex_name)
54
- Object.const_get(reflex_name)
55
- else
56
- @new = true
57
- Object.const_set(reflex_name, reflex_instance)
58
- end
59
- end
60
- end
61
- end
1
+ module ViewComponentReflex
2
+ class ReflexFactory
3
+ def initialize(component)
4
+ @component = component
5
+ @new = false
6
+ reflex.component_class = component
7
+ end
8
+
9
+ def nested?
10
+ @nested ||= @component.name.include?("::")
11
+ end
12
+
13
+ def reflex_name
14
+ @reflex_name ||= if nested?
15
+ @component.name.split("::").last
16
+ else
17
+ @component.name
18
+ end + "Reflex"
19
+ end
20
+
21
+ def new?
22
+ @new
23
+ end
24
+
25
+ def reflex
26
+ @reflex ||= if nested?
27
+ reflex_from_nested_component
28
+ else
29
+ reflex_from_component
30
+ end
31
+ end
32
+
33
+ def reflex_instance
34
+ @reflex_instance ||= Class.new(@component.reflex_base_class)
35
+ end
36
+
37
+ def reflex_from_nested_component
38
+ parent = if @component.respond_to? :module_parent
39
+ @component.module_parent
40
+ else
41
+ @component.parent
42
+ end
43
+
44
+ if parent.const_defined?(reflex_name)
45
+ parent.const_get(reflex_name)
46
+ else
47
+ @new = true
48
+ parent.const_set(reflex_name, reflex_instance)
49
+ end
50
+ end
51
+
52
+ def reflex_from_component
53
+ if Object.const_defined?(reflex_name)
54
+ Object.const_get(reflex_name)
55
+ else
56
+ @new = true
57
+ Object.const_set(reflex_name, reflex_instance)
58
+ end
59
+ end
60
+ end
61
+ end