view_component_reflex 3.1.14.pre3 → 3.1.14.pre7

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,230 +1,230 @@
1
- module ViewComponentReflex
2
- class Reflex < StimulusReflex::Reflex
3
-
4
- class << self
5
- attr_accessor :component_class
6
- end
7
-
8
- # pretty sure I can't memoize this because we need
9
- # to re-render every time
10
- def controller_document
11
- controller.process(params[:action])
12
- Nokogiri::HTML(controller.response.body)
13
- end
14
-
15
- def refresh!(primary_selector = nil, *rest)
16
- save_state
17
-
18
- if primary_selector.nil? && !component.can_render_to_string?
19
- primary_selector = selector
20
- end
21
- if primary_selector
22
- prevent_refresh!
23
-
24
- document = controller_document
25
- [primary_selector, *rest].each do |s|
26
- html = document.css(s)
27
- if html.present?
28
- CableReady::Channels.instance[stream].morph(
29
- selector: s,
30
- html: html.inner_html,
31
- children_only: true,
32
- permanent_attribute_name: "data-reflex-permanent",
33
- reflex_id: reflex_id
34
- )
35
- end
36
- end
37
- else
38
- refresh_component!
39
- end
40
- CableReady::Channels.instance[stream].broadcast
41
- end
42
-
43
- def stream
44
- @stream ||= stream_name
45
- end
46
-
47
- def stream_to(channel)
48
- @stream = channel
49
- end
50
-
51
- def component_document
52
- component.tap do |k|
53
- k.define_singleton_method(:initialize_component) do
54
- @key = element.dataset[:key]
55
- end
56
- end
57
-
58
- document = Nokogiri::HTML(component.render_in(controller.view_context))
59
- end
60
-
61
- def refresh_component!
62
- CableReady::Channels.instance[stream].morph(
63
- selector: selector,
64
- children_only: true,
65
- html: component_document.css(selector).inner_html,
66
- permanent_attribute_name: "data-reflex-permanent",
67
- reflex_id: reflex_id
68
- )
69
- end
70
-
71
- def default_morph
72
- save_state
73
- html = if component.can_render_to_string?
74
- component_document.css(selector).to_html
75
- else
76
- controller_document.css(selector).to_html
77
- end
78
- morph selector, html
79
- end
80
-
81
- def stimulus_reflex_data
82
- {
83
- reflex_id: reflex_id,
84
- xpath_controller: xpath_controller,
85
- xpath_element: xpath_element,
86
- target: target,
87
- reflex_controller: reflex_controller,
88
- url: url,
89
- morph: :page,
90
- attrs: {
91
- key: element.dataset[:key]
92
- }
93
- }
94
- end
95
-
96
- def target
97
- "#{component_class}##{method_name}"
98
- end
99
-
100
- def refresh_all!
101
- refresh!("body")
102
- end
103
-
104
- def selector
105
- "[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]"
106
- end
107
-
108
- # SR's delegate_call_to_reflex in channel.rb
109
- # uses method to gather the method parameters, but since we're abusing
110
- # method_missing here, that'll always fail
111
- def method(name)
112
- component.method(name.to_sym)
113
- end
114
-
115
- def respond_to_missing?(name, _ = false)
116
- !!name.to_proc
117
- end
118
-
119
- def method_missing(name, *args, &blk)
120
- super unless respond_to_missing?(name)
121
-
122
- state.each do |k, v|
123
- component.instance_variable_set(k, v)
124
- end
125
-
126
- component.send(name, *args, &blk)
127
-
128
- if @prevent_refresh
129
- morph :nothing
130
- else
131
- default_morph
132
- end
133
- end
134
-
135
- def prevent_refresh!
136
- @prevent_refresh = true
137
- end
138
-
139
- private
140
-
141
- def component_class
142
- self.class.component_class
143
- end
144
-
145
- def stimulus_controller
146
- component_class.stimulus_controller
147
- end
148
-
149
- def stimulate(target, data)
150
- data_to_receive = {
151
- "dataset" => {
152
- "datasetAll" => {},
153
- "dataset" => {}
154
- }
155
- }
156
-
157
- stimulus_reflex_data.each do |k, v|
158
- data_to_receive[k.to_s.camelize(:lower)] = v
159
- end
160
-
161
- data_to_receive["dataset"]["dataset"] = data.each_with_object({}) do |(k, v), o|
162
- o["data-#{k}"] = v
163
- end
164
-
165
- data_to_receive["attrs"] = element.attributes.to_h.symbolize_keys
166
- data_to_receive["target"] = target
167
-
168
- channel.receive data_to_receive
169
- end
170
-
171
- def component
172
- return @component if @component
173
- @component = component_class.allocate
174
- reflex = self
175
- exposed_methods = [
176
- :params,
177
- :request,
178
- :connection,
179
- :element,
180
- :refresh!,
181
- :refresh_all!,
182
- :stimulus_controller,
183
- :session,
184
- :prevent_refresh!,
185
- :selector,
186
- :stimulate,
187
- :stream_to
188
- ]
189
- exposed_methods.each do |meth|
190
- @component.define_singleton_method(meth) do |*a|
191
- reflex.send(meth, *a)
192
- end
193
- end
194
-
195
- @component.define_singleton_method(:reflex) do
196
- reflex
197
- end
198
-
199
- @component
200
- end
201
-
202
- def set_state(new_state = {})
203
- state_adapter.set_state(request, controller, key, new_state)
204
- end
205
-
206
- def key
207
- element.dataset[:key]
208
- end
209
-
210
- def state_adapter
211
- ViewComponentReflex::Engine.state_adapter
212
- end
213
-
214
- def state
215
- state_adapter.state(request, key)
216
- end
217
-
218
- def initial_state
219
- state_adapter.state(request, "#{key}_initial")
220
- end
221
-
222
- def save_state
223
- new_state = {}
224
- component.safe_instance_variables.each do |k|
225
- new_state[k] = component.instance_variable_get(k)
226
- end
227
- set_state(new_state)
228
- end
229
- end
230
- end
1
+ module ViewComponentReflex
2
+ class Reflex < StimulusReflex::Reflex
3
+
4
+ class << self
5
+ attr_accessor :component_class
6
+ end
7
+
8
+ # pretty sure I can't memoize this because we need
9
+ # to re-render every time
10
+ def controller_document
11
+ controller.process(params[:action])
12
+ Nokogiri::HTML(controller.response.body)
13
+ end
14
+
15
+ def refresh!(primary_selector = nil, *rest)
16
+ save_state
17
+
18
+ if primary_selector.nil? && !component.can_render_to_string?
19
+ primary_selector = selector
20
+ end
21
+ if primary_selector
22
+ prevent_refresh!
23
+
24
+ document = controller_document
25
+ [primary_selector, *rest].each do |s|
26
+ html = document.css(s)
27
+ if html.present?
28
+ CableReady::Channels.instance[stream].morph(
29
+ selector: s,
30
+ html: html.inner_html,
31
+ children_only: true,
32
+ permanent_attribute_name: "data-reflex-permanent",
33
+ reflex_id: reflex_id
34
+ )
35
+ end
36
+ end
37
+ else
38
+ refresh_component!
39
+ end
40
+ CableReady::Channels.instance[stream].broadcast
41
+ end
42
+
43
+ def stream
44
+ @stream ||= stream_name
45
+ end
46
+
47
+ def stream_to(channel)
48
+ @stream = channel
49
+ end
50
+
51
+ def component_document
52
+ component.tap do |k|
53
+ k.define_singleton_method(:initialize_component) do
54
+ @key = element.dataset[:key]
55
+ end
56
+ end
57
+
58
+ document = Nokogiri::HTML(component.render_in(controller.view_context))
59
+ end
60
+
61
+ def refresh_component!
62
+ CableReady::Channels.instance[stream].morph(
63
+ selector: selector,
64
+ children_only: true,
65
+ html: component_document.css(selector).inner_html,
66
+ permanent_attribute_name: "data-reflex-permanent",
67
+ reflex_id: reflex_id
68
+ )
69
+ end
70
+
71
+ def default_morph
72
+ save_state
73
+ html = if component.can_render_to_string?
74
+ component_document.css(selector).to_html
75
+ else
76
+ controller_document.css(selector).to_html
77
+ end
78
+ morph selector, html
79
+ end
80
+
81
+ def stimulus_reflex_data
82
+ {
83
+ reflex_id: reflex_id,
84
+ xpath_controller: xpath_controller,
85
+ xpath_element: xpath_element,
86
+ target: target,
87
+ reflex_controller: reflex_controller,
88
+ url: url,
89
+ morph: :page,
90
+ attrs: {
91
+ key: element.dataset[:key]
92
+ }
93
+ }
94
+ end
95
+
96
+ def target
97
+ "#{component_class}##{method_name}"
98
+ end
99
+
100
+ def refresh_all!
101
+ refresh!("body")
102
+ end
103
+
104
+ def selector
105
+ "[data-controller~=\"#{stimulus_controller}\"][data-key=\"#{element.dataset[:key]}\"]"
106
+ end
107
+
108
+ # SR's delegate_call_to_reflex in channel.rb
109
+ # uses method to gather the method parameters, but since we're abusing
110
+ # method_missing here, that'll always fail
111
+ def method(name)
112
+ component.method(name.to_sym)
113
+ end
114
+
115
+ def respond_to_missing?(name, _ = false)
116
+ !!name.to_proc
117
+ end
118
+
119
+ def method_missing(name, *args, &blk)
120
+ super unless respond_to_missing?(name)
121
+
122
+ state.each do |k, v|
123
+ component.instance_variable_set(k, v)
124
+ end
125
+
126
+ component.send(name, *args, &blk)
127
+
128
+ if @prevent_refresh
129
+ morph :nothing
130
+ else
131
+ default_morph
132
+ end
133
+ end
134
+
135
+ def prevent_refresh!
136
+ @prevent_refresh = true
137
+ end
138
+
139
+ private
140
+
141
+ def component_class
142
+ self.class.component_class
143
+ end
144
+
145
+ def stimulus_controller
146
+ component_class.stimulus_controller
147
+ end
148
+
149
+ def stimulate(target, data)
150
+ data_to_receive = {
151
+ "dataset" => {
152
+ "datasetAll" => {},
153
+ "dataset" => {}
154
+ }
155
+ }
156
+
157
+ stimulus_reflex_data.each do |k, v|
158
+ data_to_receive[k.to_s.camelize(:lower)] = v
159
+ end
160
+
161
+ data_to_receive["dataset"]["dataset"] = data.each_with_object({}) do |(k, v), o|
162
+ o["data-#{k}"] = v
163
+ end
164
+
165
+ data_to_receive["attrs"] = element.attributes.to_h.symbolize_keys
166
+ data_to_receive["target"] = target
167
+
168
+ channel.receive data_to_receive
169
+ end
170
+
171
+ def component
172
+ return @component if @component
173
+ @component = component_class.allocate
174
+ reflex = self
175
+ exposed_methods = [
176
+ :params,
177
+ :request,
178
+ :connection,
179
+ :element,
180
+ :refresh!,
181
+ :refresh_all!,
182
+ :stimulus_controller,
183
+ :session,
184
+ :prevent_refresh!,
185
+ :selector,
186
+ :stimulate,
187
+ :stream_to
188
+ ]
189
+ exposed_methods.each do |meth|
190
+ @component.define_singleton_method(meth) do |*a|
191
+ reflex.send(meth, *a)
192
+ end
193
+ end
194
+
195
+ @component.define_singleton_method(:reflex) do
196
+ reflex
197
+ end
198
+
199
+ @component
200
+ end
201
+
202
+ def set_state(new_state = {})
203
+ state_adapter.set_state(request, controller, key, new_state)
204
+ end
205
+
206
+ def key
207
+ element.dataset[:key]
208
+ end
209
+
210
+ def state_adapter
211
+ ViewComponentReflex::Engine.state_adapter
212
+ end
213
+
214
+ def state
215
+ state_adapter.state(request, key)
216
+ end
217
+
218
+ def initial_state
219
+ state_adapter.state(request, "#{key}_initial")
220
+ end
221
+
222
+ def save_state
223
+ new_state = {}
224
+ component.safe_instance_variables.each do |k|
225
+ new_state[k] = component.instance_variable_get(k)
226
+ end
227
+ set_state(new_state)
228
+ end
229
+ end
230
+ 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
@@ -1,18 +1,18 @@
1
- module ViewComponentReflex
2
- module StateAdapter
3
- class Base
4
-
5
- private
6
-
7
- def self.extract_id(request)
8
- session = request&.session
9
- if session.respond_to? :id
10
- session.id.to_s
11
- else
12
- nil
13
- end
14
- end
15
-
16
- end
17
- end
18
- end
1
+ module ViewComponentReflex
2
+ module StateAdapter
3
+ class Base
4
+
5
+ private
6
+
7
+ def self.extract_id(request)
8
+ session = request&.session
9
+ if session.respond_to? :id
10
+ session.id.to_s
11
+ else
12
+ nil
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -1,33 +1,33 @@
1
- VIEW_COMPONENT_REFLEX_MEMORY_STATE = {}
2
- module ViewComponentReflex
3
- module StateAdapter
4
- class Memory < Base
5
- def self.state(request, key)
6
- id = extract_id(request)
7
-
8
- VIEW_COMPONENT_REFLEX_MEMORY_STATE[id] ||= {}
9
- VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key] ||= {}
10
- end
11
-
12
- def self.set_state(request, _, key, new_state)
13
- new_state.each do |k, v|
14
- state(request, key)[k] = v
15
- end
16
- end
17
-
18
- def self.store_state(request, key, new_state = {})
19
- id = extract_id(request)
20
-
21
- VIEW_COMPONENT_REFLEX_MEMORY_STATE[id] ||= {}
22
- VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key] = {}
23
- new_state.each do |k, v|
24
- VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key][k] = v
25
- end
26
- end
27
-
28
- def self.wrap_write_async
29
- yield
30
- end
31
- end
32
- end
33
- end
1
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE = {}
2
+ module ViewComponentReflex
3
+ module StateAdapter
4
+ class Memory < Base
5
+ def self.state(request, key)
6
+ id = extract_id(request)
7
+
8
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id] ||= {}
9
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key] ||= {}
10
+ end
11
+
12
+ def self.set_state(request, _, key, new_state)
13
+ new_state.each do |k, v|
14
+ state(request, key)[k] = v
15
+ end
16
+ end
17
+
18
+ def self.store_state(request, key, new_state = {})
19
+ id = extract_id(request)
20
+
21
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id] ||= {}
22
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key] = {}
23
+ new_state.each do |k, v|
24
+ VIEW_COMPONENT_REFLEX_MEMORY_STATE[id][key][k] = v
25
+ end
26
+ end
27
+
28
+ def self.wrap_write_async
29
+ yield
30
+ end
31
+ end
32
+ end
33
+ end