view_component_reflex 3.1.2 → 3.1.3

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,198 +1,198 @@
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: xpath,
65
- target: target,
66
- c_xpath: c_xpath,
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)
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
- name.to_proc.call(component, *args)
117
- refresh! unless @prevent_refresh
118
- end
119
-
120
- def prevent_refresh!
121
- @prevent_refresh = true
122
- end
123
-
124
- private
125
-
126
- def component_class
127
- self.class.component_class
128
- end
129
-
130
- def stimulus_controller
131
- component_class.stimulus_controller
132
- end
133
-
134
- def stimulate(target, data)
135
- data_to_receive = {}
136
-
137
- stimulus_reflex_data.each do |k, v|
138
- data_to_receive[k.to_s.camelize(:lower)] = v
139
- end
140
-
141
- data_to_receive["dataset"] = data.each_with_object({}) do |(k, v), o|
142
- o["data-#{k}"] = v
143
- end
144
-
145
- data_to_receive["attrs"] = element.attributes.to_h.symbolize_keys
146
- data_to_receive["target"] = target
147
-
148
- channel.receive data_to_receive
149
- end
150
-
151
- def component
152
- return @component if @component
153
- @component = component_class.allocate
154
- reflex = self
155
- exposed_methods = [
156
- :params,
157
- :request,
158
- :connection,
159
- :element,
160
- :refresh!,
161
- :refresh_all!,
162
- :stimulus_controller,
163
- :session,
164
- :prevent_refresh!,
165
- :selector,
166
- :stimulate,
167
- :stream_to
168
- ]
169
- exposed_methods.each do |meth|
170
- @component.define_singleton_method(meth) do |*a|
171
- reflex.send(meth, *a)
172
- end
173
- end
174
-
175
- @component.define_singleton_method(:reflex) do
176
- reflex
177
- end
178
-
179
- @component
180
- end
181
-
182
- def set_state(new_state = {})
183
- ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
184
- end
185
-
186
- def state
187
- ViewComponentReflex::Engine.state_adapter.state(request, element.dataset[:key])
188
- end
189
-
190
- def save_state
191
- new_state = {}
192
- component.safe_instance_variables.each do |k|
193
- new_state[k] = component.instance_variable_get(k)
194
- end
195
- set_state(new_state)
196
- end
197
- end
198
- 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: xpath,
65
+ target: target,
66
+ c_xpath: c_xpath,
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)
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
+ name.to_proc.call(component, *args)
117
+ refresh! unless @prevent_refresh
118
+ end
119
+
120
+ def prevent_refresh!
121
+ @prevent_refresh = true
122
+ end
123
+
124
+ private
125
+
126
+ def component_class
127
+ self.class.component_class
128
+ end
129
+
130
+ def stimulus_controller
131
+ component_class.stimulus_controller
132
+ end
133
+
134
+ def stimulate(target, data)
135
+ data_to_receive = {}
136
+
137
+ stimulus_reflex_data.each do |k, v|
138
+ data_to_receive[k.to_s.camelize(:lower)] = v
139
+ end
140
+
141
+ data_to_receive["dataset"] = data.each_with_object({}) do |(k, v), o|
142
+ o["data-#{k}"] = v
143
+ end
144
+
145
+ data_to_receive["attrs"] = element.attributes.to_h.symbolize_keys
146
+ data_to_receive["target"] = target
147
+
148
+ channel.receive data_to_receive
149
+ end
150
+
151
+ def component
152
+ return @component if @component
153
+ @component = component_class.allocate
154
+ reflex = self
155
+ exposed_methods = [
156
+ :params,
157
+ :request,
158
+ :connection,
159
+ :element,
160
+ :refresh!,
161
+ :refresh_all!,
162
+ :stimulus_controller,
163
+ :session,
164
+ :prevent_refresh!,
165
+ :selector,
166
+ :stimulate,
167
+ :stream_to
168
+ ]
169
+ exposed_methods.each do |meth|
170
+ @component.define_singleton_method(meth) do |*a|
171
+ reflex.send(meth, *a)
172
+ end
173
+ end
174
+
175
+ @component.define_singleton_method(:reflex) do
176
+ reflex
177
+ end
178
+
179
+ @component
180
+ end
181
+
182
+ def set_state(new_state = {})
183
+ ViewComponentReflex::Engine.state_adapter.set_state(request, controller, element.dataset[:key], new_state)
184
+ end
185
+
186
+ def state
187
+ ViewComponentReflex::Engine.state_adapter.state(request, element.dataset[:key])
188
+ end
189
+
190
+ def save_state
191
+ new_state = {}
192
+ component.safe_instance_variables.each do |k|
193
+ new_state[k] = component.instance_variable_get(k)
194
+ end
195
+ set_state(new_state)
196
+ end
197
+ end
198
+ 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