view_component_reflex 2.3.4 → 2.3.5

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 Component < ViewComponent::Base
3
- class << self
4
- def init_stimulus_reflex
5
- factory = ViewComponentReflex::ReflexFactory.new(self)
6
- @stimulus_reflex ||= factory.reflex
7
- wire_up_callbacks if factory.new?
8
- end
9
-
10
- def reflex_base_class(new_base_class = nil)
11
- if new_base_class.nil?
12
- @reflex_base_class ||= ViewComponentReflex::Reflex
13
- else
14
- if new_base_class <= ViewComponentReflex::Reflex
15
- @reflex_base_class = new_base_class
16
- else
17
- raise StandardError.new("The reflex base class must inherit from ViewComponentReflex::Reflex")
18
- end
19
- end
20
- end
21
-
22
- def queue_callback(key, args, blk)
23
- callbacks(key).push({
24
- args: args,
25
- blk: blk
26
- })
27
- end
28
-
29
- def callbacks(key)
30
- @callbacks ||= {}
31
- @callbacks[key] ||= []
32
- end
33
-
34
- def register_callbacks(key)
35
- callbacks(key).each do |cb|
36
- @stimulus_reflex.send("#{key}_reflex", *cb[:args], &cb[:blk])
37
- end
38
- end
39
-
40
- def before_reflex(*args, &blk)
41
- queue_callback(:before, args, blk)
42
- end
43
-
44
- def after_reflex(*args, &blk)
45
- queue_callback(:after, args, blk)
46
- end
47
-
48
- def around_reflex(*args, &blk)
49
- queue_callback(:around, args, blk)
50
- end
51
-
52
- def wire_up_callbacks
53
- register_callbacks(:before)
54
- register_callbacks(:after)
55
- register_callbacks(:around)
56
- end
57
- end
58
-
59
- def self.stimulus_controller
60
- name.chomp("Component").underscore.dasherize
61
- end
62
-
63
- def stimulus_reflex?
64
- helpers.controller.instance_variable_get(:@stimulus_reflex)
65
- end
66
-
67
- def component_controller(opts_or_tag = :div, opts = {}, &blk)
68
- init_key
69
-
70
- tag = :div
71
- options = if opts_or_tag.is_a? Hash
72
- opts_or_tag
73
- else
74
- tag = opts_or_tag
75
- opts
76
- end
77
-
78
- options[:data] = {
79
- controller: self.class.stimulus_controller,
80
- key: key,
81
- **(options[:data] || {})
82
- }
83
- content_tag tag, capture(&blk), options
84
- end
85
-
86
- def can_render_to_string?
87
- omitted_from_state.empty?
88
- end
89
-
90
- # key is required if you're using state
91
- # We can't initialize the session state in the initial method
92
- # because it doesn't have a view_context yet
93
- # This is the next best place to do it
94
- def init_key
95
- # we want the erb file that renders the component. `caller` gives the file name,
96
- # and line number, which should be unique. We hash it to make it a nice number
97
- erb_file = caller.select { |p| p.match? /.\.html\.(haml|erb|slim)/ }[1]
98
- key = if erb_file
99
- Digest::SHA2.hexdigest(erb_file.split(":in")[0])
100
- else
101
- ""
102
- end
103
- key += collection_key.to_s if collection_key
104
- @key = key
105
- end
106
-
107
- # Helper to use to create the proper reflex data attributes for an element
108
- def reflex_data_attributes(reflex)
109
- action, method = reflex.to_s.split("->")
110
- if method.nil?
111
- method = action
112
- action = "click"
113
- end
114
-
115
- {
116
- reflex: "#{action}->#{self.class.name}##{method}",
117
- key: key
118
- }
119
- end
120
-
121
- def reflex_tag(reflex, name, content_or_options_with_block = {}, options = {}, escape = true, &block)
122
- if content_or_options_with_block.is_a?(Hash)
123
- merge_data_attributes(content_or_options_with_block, reflex_data_attributes(reflex))
124
- else
125
- merge_data_attributes(options, reflex_data_attributes(reflex))
126
- end
127
- content_tag(name, content_or_options_with_block, options, escape, &block)
128
- end
129
-
130
- def collection_key
131
- nil
132
- end
133
-
134
- def permit_parameter?(initial_param, new_param)
135
- initial_param != new_param
136
- end
137
-
138
- def omitted_from_state
139
- []
140
- end
141
-
142
- def key
143
- # initialize session state
144
- if !stimulus_reflex? || ViewComponentReflex::Engine.state_adapter.state(request, @key).empty?
145
-
146
- new_state = create_safe_state
147
-
148
- ViewComponentReflex::Engine.state_adapter.store_state(request, @key, new_state)
149
- ViewComponentReflex::Engine.state_adapter.store_state(request, "#{@key}_initial", new_state)
150
- else
151
- initial_state = ViewComponentReflex::Engine.state_adapter.state(request, "#{@key}_initial")
152
- ViewComponentReflex::Engine.state_adapter.state(request, @key).each do |k, v|
153
- instance_value = instance_variable_get(k)
154
- if permit_parameter?(initial_state[k], instance_value)
155
- # ViewComponentReflex::Engine.state_adapter.set_state(request, controller, "#{@key}_initial", {k => instance_value})
156
- ViewComponentReflex::Engine.state_adapter.set_state(request, controller, @key, {k => instance_value})
157
- else
158
- instance_variable_set(k, v)
159
- end
160
- end
161
- end
162
- @key
163
- end
164
-
165
- def safe_instance_variables
166
- instance_variables - unsafe_instance_variables
167
- end
168
-
169
- private
170
-
171
- def unsafe_instance_variables
172
- [
173
- :@view_context, :@lookup_context, :@view_renderer, :@view_flow,
174
- :@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
175
- :@helpers, :@controller, :@request, :@tag_builder
176
- ]
177
- end
178
-
179
- def create_safe_state
180
- new_state = {}
181
-
182
- # this will almost certainly break
183
- safe_instance_variables.each do |k|
184
- new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
185
- end
186
- new_state
187
- end
188
-
189
- def merge_data_attributes(options, attributes)
190
- data = options[:data]
191
- if data.nil?
192
- options[:data] = attributes
193
- else
194
- options[:data].merge! attributes
195
- end
196
- end
197
- end
198
- end
1
+ module ViewComponentReflex
2
+ class Component < ViewComponent::Base
3
+ class << self
4
+ def init_stimulus_reflex
5
+ factory = ViewComponentReflex::ReflexFactory.new(self)
6
+ @stimulus_reflex ||= factory.reflex
7
+ wire_up_callbacks if factory.new?
8
+ end
9
+
10
+ def reflex_base_class(new_base_class = nil)
11
+ if new_base_class.nil?
12
+ @reflex_base_class ||= ViewComponentReflex::Reflex
13
+ else
14
+ if new_base_class <= ViewComponentReflex::Reflex
15
+ @reflex_base_class = new_base_class
16
+ else
17
+ raise StandardError.new("The reflex base class must inherit from ViewComponentReflex::Reflex")
18
+ end
19
+ end
20
+ end
21
+
22
+ def queue_callback(key, args, blk)
23
+ callbacks(key).push({
24
+ args: args,
25
+ blk: blk
26
+ })
27
+ end
28
+
29
+ def callbacks(key)
30
+ @callbacks ||= {}
31
+ @callbacks[key] ||= []
32
+ end
33
+
34
+ def register_callbacks(key)
35
+ callbacks(key).each do |cb|
36
+ @stimulus_reflex.send("#{key}_reflex", *cb[:args], &cb[:blk])
37
+ end
38
+ end
39
+
40
+ def before_reflex(*args, &blk)
41
+ queue_callback(:before, args, blk)
42
+ end
43
+
44
+ def after_reflex(*args, &blk)
45
+ queue_callback(:after, args, blk)
46
+ end
47
+
48
+ def around_reflex(*args, &blk)
49
+ queue_callback(:around, args, blk)
50
+ end
51
+
52
+ def wire_up_callbacks
53
+ register_callbacks(:before)
54
+ register_callbacks(:after)
55
+ register_callbacks(:around)
56
+ end
57
+ end
58
+
59
+ def self.stimulus_controller
60
+ name.chomp("Component").underscore.dasherize
61
+ end
62
+
63
+ def stimulus_reflex?
64
+ helpers.controller.instance_variable_get(:@stimulus_reflex)
65
+ end
66
+
67
+ def component_controller(opts_or_tag = :div, opts = {}, &blk)
68
+ init_key
69
+
70
+ tag = :div
71
+ options = if opts_or_tag.is_a? Hash
72
+ opts_or_tag
73
+ else
74
+ tag = opts_or_tag
75
+ opts
76
+ end
77
+
78
+ options[:data] = {
79
+ controller: self.class.stimulus_controller,
80
+ key: key,
81
+ **(options[:data] || {})
82
+ }
83
+ content_tag tag, capture(&blk), options
84
+ end
85
+
86
+ def can_render_to_string?
87
+ omitted_from_state.empty?
88
+ end
89
+
90
+ # key is required if you're using state
91
+ # We can't initialize the session state in the initial method
92
+ # because it doesn't have a view_context yet
93
+ # This is the next best place to do it
94
+ def init_key
95
+ # we want the erb file that renders the component. `caller` gives the file name,
96
+ # and line number, which should be unique. We hash it to make it a nice number
97
+ erb_file = caller.select { |p| p.match? /.\.html\.(haml|erb|slim)/ }[1]
98
+ key = if erb_file
99
+ Digest::SHA2.hexdigest(erb_file.split(":in")[0])
100
+ else
101
+ ""
102
+ end
103
+ key += collection_key.to_s if collection_key
104
+ @key = key
105
+ end
106
+
107
+ # Helper to use to create the proper reflex data attributes for an element
108
+ def reflex_data_attributes(reflex)
109
+ action, method = reflex.to_s.split("->")
110
+ if method.nil?
111
+ method = action
112
+ action = "click"
113
+ end
114
+
115
+ {
116
+ reflex: "#{action}->#{self.class.name}##{method}",
117
+ key: key
118
+ }
119
+ end
120
+
121
+ def reflex_tag(reflex, name, content_or_options_with_block = {}, options = {}, escape = true, &block)
122
+ if content_or_options_with_block.is_a?(Hash)
123
+ merge_data_attributes(content_or_options_with_block, reflex_data_attributes(reflex))
124
+ else
125
+ merge_data_attributes(options, reflex_data_attributes(reflex))
126
+ end
127
+ content_tag(name, content_or_options_with_block, options, escape, &block)
128
+ end
129
+
130
+ def collection_key
131
+ nil
132
+ end
133
+
134
+ def permit_parameter?(initial_param, new_param)
135
+ initial_param != new_param
136
+ end
137
+
138
+ def omitted_from_state
139
+ []
140
+ end
141
+
142
+ def key
143
+ # initialize session state
144
+ if !stimulus_reflex? || ViewComponentReflex::Engine.state_adapter.state(request, @key).empty?
145
+
146
+ new_state = create_safe_state
147
+
148
+ ViewComponentReflex::Engine.state_adapter.store_state(request, @key, new_state)
149
+ ViewComponentReflex::Engine.state_adapter.store_state(request, "#{@key}_initial", new_state)
150
+ else
151
+ initial_state = ViewComponentReflex::Engine.state_adapter.state(request, "#{@key}_initial")
152
+ ViewComponentReflex::Engine.state_adapter.state(request, @key).each do |k, v|
153
+ instance_value = instance_variable_get(k)
154
+ if permit_parameter?(initial_state[k], instance_value)
155
+ ViewComponentReflex::Engine.state_adapter.set_state(request, controller, "#{@key}_initial", {k => instance_value})
156
+ ViewComponentReflex::Engine.state_adapter.set_state(request, controller, @key, {k => instance_value})
157
+ else
158
+ instance_variable_set(k, v)
159
+ end
160
+ end
161
+ end
162
+ @key
163
+ end
164
+
165
+ def safe_instance_variables
166
+ instance_variables - unsafe_instance_variables
167
+ end
168
+
169
+ private
170
+
171
+ def unsafe_instance_variables
172
+ [
173
+ :@view_context, :@lookup_context, :@view_renderer, :@view_flow,
174
+ :@virtual_path, :@variant, :@current_template, :@output_buffer, :@key,
175
+ :@helpers, :@controller, :@request, :@tag_builder
176
+ ]
177
+ end
178
+
179
+ def create_safe_state
180
+ new_state = {}
181
+
182
+ # this will almost certainly break
183
+ safe_instance_variables.each do |k|
184
+ new_state[k] = instance_variable_get(k) unless omitted_from_state.include?(k)
185
+ end
186
+ new_state
187
+ end
188
+
189
+ def merge_data_attributes(options, attributes)
190
+ data = options[:data]
191
+ if data.nil?
192
+ options[:data] = attributes
193
+ else
194
+ options[:data].merge! attributes
195
+ end
196
+ end
197
+ end
198
+ end
@@ -1,10 +1,10 @@
1
- require "stimulus_reflex"
2
- require 'view_component_reflex/reflex_factory'
3
- require "view_component_reflex/state_adapter/session"
4
- require "view_component_reflex/state_adapter/memory"
5
- require "view_component_reflex/reflex"
6
- require "view_component_reflex/engine"
7
-
8
- module ViewComponentReflex
9
- # Your code goes here...
10
- end
1
+ require "stimulus_reflex"
2
+ require 'view_component_reflex/reflex_factory'
3
+ require "view_component_reflex/state_adapter/session"
4
+ require "view_component_reflex/state_adapter/memory"
5
+ require "view_component_reflex/reflex"
6
+ require "view_component_reflex/engine"
7
+
8
+ module ViewComponentReflex
9
+ # Your code goes here...
10
+ end
@@ -1,36 +1,36 @@
1
- module ViewComponentReflex
2
- class Engine < ::Rails::Engine
3
- class << self
4
- mattr_accessor :state_adapter
5
-
6
- self.state_adapter = StateAdapter::Session
7
- end
8
-
9
- config.to_prepare do
10
- StimulusReflex::Channel.class_eval do
11
- unless instance_methods.include?(:receive_original)
12
- alias_method :receive_original, :receive
13
- def receive(data)
14
- target = data["target"].to_s
15
- reflex_name, _ = target.split("#")
16
- reflex_name = reflex_name.camelize
17
- component_name = reflex_name.end_with?("Reflex") ? reflex_name[0...-6] : reflex_name
18
- if component_name.end_with?("Component")
19
- begin
20
- component_name.constantize.init_stimulus_reflex
21
- rescue
22
- p "Tried to initialize view_component_reflex on #{component_name}, but it's not a view_component_reflex"
23
- end
24
-
25
- end
26
- receive_original(data)
27
- end
28
- end
29
- end
30
- end
31
-
32
- def self.configure
33
- yield self if block_given?
34
- end
35
- end
36
- end
1
+ module ViewComponentReflex
2
+ class Engine < ::Rails::Engine
3
+ class << self
4
+ mattr_accessor :state_adapter
5
+
6
+ self.state_adapter = StateAdapter::Session
7
+ end
8
+
9
+ config.to_prepare do
10
+ StimulusReflex::Channel.class_eval do
11
+ unless instance_methods.include?(:receive_original)
12
+ alias_method :receive_original, :receive
13
+ def receive(data)
14
+ target = data["target"].to_s
15
+ reflex_name, _ = target.split("#")
16
+ reflex_name = reflex_name.camelize
17
+ component_name = reflex_name.end_with?("Reflex") ? reflex_name[0...-6] : reflex_name
18
+ if component_name.end_with?("Component")
19
+ begin
20
+ component_name.constantize.init_stimulus_reflex
21
+ rescue
22
+ p "Tried to initialize view_component_reflex on #{component_name}, but it's not a view_component_reflex"
23
+ end
24
+
25
+ end
26
+ receive_original(data)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.configure
33
+ yield self if block_given?
34
+ end
35
+ end
36
+ end