view_component-contrib 0.1.6 → 0.2.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +187 -21
- data/lib/view_component_contrib/style_variants.rb +184 -0
- data/lib/view_component_contrib/version.rb +1 -1
- data/lib/view_component_contrib.rb +1 -0
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b586c9ad03730cff1cc38721c6904f427c71a73f5777605f17fc0379f60f8dc7
|
4
|
+
data.tar.gz: 7c2ed9aed5c845492a8487fab7ce5e66c639d455d8b4027c383b047ad961fdf0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1d2f760734b6ca7f71da538fbba4c04b0ff91b885cc47e09f3943b81a5a097ef62293348dc3ac07e20a4b812e52cf8a4bd8b39b6cb306551dceac4a784c652b
|
7
|
+
data.tar.gz: baaf5f34009ca87228246f260357339849f3d22e988543f36c36e772293bede4f249741fee5749db46d37a78dd8dc94674e13181d618282463a31afd5dba48b7
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,20 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.2.1 (2023-11-16)
|
6
|
+
|
7
|
+
- Fix style variants inhertiance. ([@palkan][])
|
8
|
+
|
9
|
+
## 0.2.0 (2023-11-07)
|
10
|
+
|
11
|
+
- Introduce style variants. ([@palkan][])
|
12
|
+
|
13
|
+
- **Require Ruby 2.7+**. ([@palkan][])
|
14
|
+
|
15
|
+
- Add system tests to generator. ([@palkan][])
|
16
|
+
|
17
|
+
- Drop Webpack-related stuff from the generator. ([@palkan][])
|
18
|
+
|
5
19
|
## 0.1.6 (2023-11-07)
|
6
20
|
|
7
21
|
- Support preview classes named `<component|partial>_preview.rb`. ([@palkan][])
|
data/README.md
CHANGED
@@ -32,7 +32,6 @@ The command above:
|
|
32
32
|
- Configure `view_component` paths.
|
33
33
|
- Adds `ApplicationViewComponent` and `ApplicationViewComponentPreview` classes.
|
34
34
|
- Configures testing framework (RSpec or Minitest).
|
35
|
-
- Adds required JS/CSS configuration.
|
36
35
|
- **Adds a custom generator to create components**.
|
37
36
|
|
38
37
|
The custom generator would allow you to create all the required component files in a single command:
|
@@ -94,6 +93,8 @@ ActiveSupport.on_load(:view_component) do
|
|
94
93
|
end
|
95
94
|
```
|
96
95
|
|
96
|
+
You can still continue using preview clases with the `_preview.rb` suffix, they would work as before.
|
97
|
+
|
97
98
|
#### Reducing previews boilerplate
|
98
99
|
|
99
100
|
In most cases, previews contain only the `default` example and a very simple template (`= render Component.new(**options)`).
|
@@ -180,9 +181,125 @@ end
|
|
180
181
|
|
181
182
|
If you need more control over your template, you can add a custom `preview.html.*` template (which will be used for all examples in this preview), or even create an example-specific `previews/example.html.*` (e.g. `previews/mobile.html.erb`).
|
182
183
|
|
184
|
+
## Style variants
|
185
|
+
|
186
|
+
Since v0.2.0, we provide a custom extentions to manage CSS classes and their combinations—**Style Variants**. This is especially useful for project using CSS frameworks such as TailwindCSS.
|
187
|
+
|
188
|
+
The idea is to define variants schema in the component class and use it to compile the resulting list of CSS classes. (Inspired by [Tailwind Variants](https://www.tailwind-variants.org) and [CVA variants](https://cva.style/docs/getting-started/variants)).
|
189
|
+
|
190
|
+
Consider an example:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
class ButtonComponent < ViewComponent::Base
|
194
|
+
include ViewComponentContrib::StyleVariants
|
195
|
+
|
196
|
+
style do
|
197
|
+
base {
|
198
|
+
%w[
|
199
|
+
font-medium bg-blue-500 text-white rounded-full
|
200
|
+
]
|
201
|
+
}
|
202
|
+
variants {
|
203
|
+
color {
|
204
|
+
primary { %w[bg-blue-500 text-white] }
|
205
|
+
secondary { %w[bg-purple-500 text-white] }
|
206
|
+
}
|
207
|
+
size {
|
208
|
+
sm { "text-sm" }
|
209
|
+
md { "text-base" }
|
210
|
+
lg { "px-4 py-3 text-lg" }
|
211
|
+
}
|
212
|
+
}
|
213
|
+
defaults { {size: :md, color: :primary} }
|
214
|
+
end
|
215
|
+
|
216
|
+
attr_reader :size, :color
|
217
|
+
|
218
|
+
def initialize(size: nil, color: nil)
|
219
|
+
@size = size
|
220
|
+
@color = color
|
221
|
+
end
|
222
|
+
end
|
223
|
+
```
|
224
|
+
|
225
|
+
Now, in the template, you can use the `#style` method and pass the variants to it:
|
226
|
+
|
227
|
+
```erb
|
228
|
+
<button class="<%= style(size:, color:) %>">Click me</button>
|
229
|
+
```
|
230
|
+
|
231
|
+
Passing `size: :lg` and `color: :secondary` would result in the following HTML:
|
232
|
+
|
233
|
+
```html
|
234
|
+
<button class="font-medium bg-purple-500 text-white rounded-full px-4 py-3 text-lg">Click me</button>
|
235
|
+
```
|
236
|
+
|
237
|
+
**NOTE:** If you pass `nil`, the default value would be used.
|
238
|
+
|
239
|
+
You can define multiple style sets in a single component:
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
class ButtonComponent < ViewComponent::Base
|
243
|
+
include ViewComponentContrib::StyleVariants
|
244
|
+
|
245
|
+
# default component styles
|
246
|
+
style do
|
247
|
+
# ...
|
248
|
+
end
|
249
|
+
|
250
|
+
style :image do
|
251
|
+
variants {
|
252
|
+
orient {
|
253
|
+
portrait { "w-32 h-32" }
|
254
|
+
landscape { "w-64 h-32" }
|
255
|
+
}
|
256
|
+
}
|
257
|
+
end
|
258
|
+
end
|
259
|
+
```
|
260
|
+
|
261
|
+
And in the template:
|
262
|
+
|
263
|
+
```erb
|
264
|
+
<div>
|
265
|
+
<button class="<%= style(size:, theme:) %>">Click me</button>
|
266
|
+
<img src="..." class="<%= style(:image, orient: :portrait) %>">
|
267
|
+
</div>
|
268
|
+
```
|
269
|
+
|
270
|
+
Finally, you can inject into the class list compilation process to add your own logic:
|
271
|
+
|
272
|
+
```ruby
|
273
|
+
class ButtonComponent < ViewComponent::Base
|
274
|
+
include ViewComponentContrib::StyleVariants
|
275
|
+
|
276
|
+
# You can provide either a proc or any other callable object
|
277
|
+
style_config.postprocess_with do |classes|
|
278
|
+
# classes is an array of CSS classes
|
279
|
+
TailwindMerge.call(classes).join(" ")
|
280
|
+
end
|
281
|
+
end
|
282
|
+
```
|
283
|
+
|
284
|
+
### Using with TailwindCSS LSP
|
285
|
+
|
286
|
+
To make completions (and other LSP features) work with our DSL, try the following configuration:
|
287
|
+
|
288
|
+
```json
|
289
|
+
"tailwindCSS.includeLanguages": {
|
290
|
+
"erb": "html",
|
291
|
+
"ruby": "html"
|
292
|
+
},
|
293
|
+
"tailwindCSS.experimental.classRegex": [
|
294
|
+
"%w\\[([^\\]]*)\\]"
|
295
|
+
]
|
296
|
+
```
|
297
|
+
|
298
|
+
**NOTE:** It will only work with `%w[ ... ]` word arrays, but you can adjust it to your needs.
|
299
|
+
|
183
300
|
## Organizing assets (JS, CSS)
|
184
301
|
|
185
|
-
**NOTE
|
302
|
+
**NOTE**: This section assumes the usage of Vite or Webpack. See [this discussion](https://github.com/palkan/view_component-contrib/discussions/14) for other options.
|
186
303
|
|
187
304
|
We store JS and CSS files in the same sidecar folder:
|
188
305
|
|
@@ -203,6 +320,18 @@ import "./index.css"
|
|
203
320
|
|
204
321
|
In the root of the `components` folder we have the `index.js` file, which loads all the components:
|
205
322
|
|
323
|
+
- With Vite:
|
324
|
+
|
325
|
+
```js
|
326
|
+
// With Vite
|
327
|
+
import.meta.glob("./**/index.js").forEach((path) => {
|
328
|
+
const mod = await import(path);
|
329
|
+
mod.default();
|
330
|
+
});
|
331
|
+
```
|
332
|
+
|
333
|
+
- With Webpack:
|
334
|
+
|
206
335
|
```js
|
207
336
|
// components/index.js
|
208
337
|
const context = require.context(".", true, /index.js$/)
|
@@ -211,12 +340,11 @@ context.keys().forEach(context);
|
|
211
340
|
|
212
341
|
### Using with StimulusJS
|
213
342
|
|
214
|
-
You can define Stimulus controllers right in the `
|
343
|
+
You can define Stimulus controllers right in the component folder in the `controller.js` file:
|
215
344
|
|
216
345
|
```js
|
217
|
-
import "./index.css"
|
218
346
|
// We reserve Controller for the export name
|
219
|
-
import { Controller as BaseController } from "stimulus";
|
347
|
+
import { Controller as BaseController } from "@hotwired/stimulus";
|
220
348
|
|
221
349
|
export class Controller extends BaseController {
|
222
350
|
connect() {
|
@@ -225,20 +353,60 @@ export class Controller extends BaseController {
|
|
225
353
|
}
|
226
354
|
```
|
227
355
|
|
228
|
-
Then,
|
356
|
+
Then, in your Stimulus entrypoint, you can load and register your component controllers as follows:
|
357
|
+
|
358
|
+
- With Vite:
|
229
359
|
|
230
360
|
```js
|
231
|
-
|
232
|
-
|
361
|
+
import { Application } from "@hotwired/stimulus";
|
362
|
+
|
363
|
+
const application = Application.start();
|
364
|
+
|
365
|
+
// Configure Stimulus development experience
|
366
|
+
application.debug = false;
|
367
|
+
window.Stimulus = application;
|
368
|
+
|
369
|
+
// Generic controllers
|
370
|
+
const genericControllers = import.meta.globEager(
|
371
|
+
"../controllers/**/*_controller.js"
|
372
|
+
);
|
373
|
+
|
374
|
+
for (let path in genericControllers) {
|
375
|
+
let module = genericControllers[path];
|
376
|
+
let name = path
|
377
|
+
.match(/controllers\/(.+)_controller\.js$/)[1]
|
378
|
+
.replaceAll("/", "-")
|
379
|
+
.replaceAll("_", "-");
|
380
|
+
|
381
|
+
application.register(name, module.default);
|
382
|
+
}
|
383
|
+
|
384
|
+
// Controllers from components
|
385
|
+
const controllers = import.meta.globEager(
|
386
|
+
"./../../app/frontend/components/**/controller.js"
|
387
|
+
);
|
388
|
+
|
389
|
+
for (let path in controllers) {
|
390
|
+
let module = controllers[path];
|
391
|
+
let name = path
|
392
|
+
.match(/app\/frontend\/components\/(.+)\/controller\.js$/)[1]
|
393
|
+
.replaceAll("/", "-")
|
394
|
+
.replaceAll("_", "-");
|
395
|
+
application.register(name, module.default);
|
396
|
+
}
|
233
397
|
|
234
|
-
|
398
|
+
export default application;
|
399
|
+
```
|
400
|
+
|
401
|
+
- With Webpack:
|
402
|
+
|
403
|
+
```js
|
235
404
|
import { Application } from "stimulus";
|
236
405
|
export const application = Application.start();
|
237
406
|
|
238
|
-
//
|
239
|
-
import { application } from "../init/stimulus";
|
407
|
+
// ... other controllers
|
240
408
|
|
241
|
-
const context = require.context("
|
409
|
+
const context = require.context("./../../app/frontend/components/", true, /controllers.js$/)
|
242
410
|
context.keys().forEach((path) => {
|
243
411
|
const mod = context(path);
|
244
412
|
|
@@ -248,9 +416,10 @@ context.keys().forEach((path) => {
|
|
248
416
|
// Convert path into a controller identifier:
|
249
417
|
// example/index.js -> example
|
250
418
|
// nav/user_info/index.js -> nav--user-info
|
251
|
-
const identifier = path
|
252
|
-
.
|
253
|
-
.
|
419
|
+
const identifier = path
|
420
|
+
.match(/app\/frontend\/components\/(.+)\/controller\.js$/)[1]
|
421
|
+
.replaceAll("/", "-")
|
422
|
+
.replaceAll("_", "-");
|
254
423
|
|
255
424
|
application.register(identifier, mod.Controller);
|
256
425
|
});
|
@@ -265,6 +434,8 @@ class ApplicationViewComponent
|
|
265
434
|
def identifier
|
266
435
|
@identifier ||= self.class.name.sub("::Component", "").underscore.split("/").join("--")
|
267
436
|
end
|
437
|
+
|
438
|
+
alias_method :controller_name, :identifier
|
268
439
|
end
|
269
440
|
```
|
270
441
|
|
@@ -272,7 +443,7 @@ And now in your template:
|
|
272
443
|
|
273
444
|
```erb
|
274
445
|
<!-- component.html -->
|
275
|
-
<div data-controller="<%=
|
446
|
+
<div data-controller="<%= controller_name %>">
|
276
447
|
</div>
|
277
448
|
```
|
278
449
|
|
@@ -495,11 +666,6 @@ And the template looks like this now:
|
|
495
666
|
|
496
667
|
You can use the `#wrapped` method on any component inherited from `ApplicationViewComponent` to wrap it automatically:
|
497
668
|
|
498
|
-
## ToDo list
|
499
|
-
|
500
|
-
- Better preview tools (w/o JS deps 😉).
|
501
|
-
- Hotwire-related extensions.
|
502
|
-
|
503
669
|
## License
|
504
670
|
|
505
671
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
# Organize style in variants that can be combined.
|
5
|
+
# Inspired by https://www.tailwind-variants.org and https://cva.style/docs/getting-started/variants
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# class ButtonComponent < ViewComponent::Base
|
10
|
+
# include ViewComponentContrib::StyleVariants
|
11
|
+
#
|
12
|
+
# erb_template <<~ERB
|
13
|
+
# <button class="<%= style(size: 'sm', color: 'secondary') %>">Click me</button>
|
14
|
+
# ERB
|
15
|
+
#
|
16
|
+
# style do
|
17
|
+
# base {
|
18
|
+
# %w(
|
19
|
+
# font-medium bg-blue-500 text-white rounded-full
|
20
|
+
# )
|
21
|
+
# }
|
22
|
+
# variants {
|
23
|
+
# color {
|
24
|
+
# primary { %w(bg-blue-500 text-white) }
|
25
|
+
# secondary { %w(bg-purple-500 text-white) }
|
26
|
+
# }
|
27
|
+
# size {
|
28
|
+
# sm { "text-sm" }
|
29
|
+
# md { "text-base" }
|
30
|
+
# lg { "px-4 py-3 text-lg" }
|
31
|
+
# }
|
32
|
+
# }
|
33
|
+
# defaults { {size: :md, color: :primary} }
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# attr_reader :size, :color
|
37
|
+
#
|
38
|
+
# def initialize(size: :md, color: :primary)
|
39
|
+
# @size = size
|
40
|
+
# @color = color
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
module StyleVariants
|
45
|
+
class VariantBuilder
|
46
|
+
attr_reader :unwrap_blocks
|
47
|
+
|
48
|
+
def initialize(unwrap_blocks = true)
|
49
|
+
@unwrap_blocks = unwrap_blocks
|
50
|
+
@variants = {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def build(&block)
|
54
|
+
instance_eval(&block)
|
55
|
+
@variants
|
56
|
+
end
|
57
|
+
|
58
|
+
def respond_to_missing?(name, include_private = false)
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def method_missing(name, &block)
|
63
|
+
return super unless block_given?
|
64
|
+
|
65
|
+
@variants[name] = if unwrap_blocks
|
66
|
+
VariantBuilder.new(false).build(&block)
|
67
|
+
else
|
68
|
+
block
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class StyleSet
|
74
|
+
def initialize(&init_block)
|
75
|
+
@base_block = nil
|
76
|
+
@defaults = {}
|
77
|
+
@variants = {}
|
78
|
+
|
79
|
+
instance_eval(&init_block) if init_block
|
80
|
+
end
|
81
|
+
|
82
|
+
def base(&block)
|
83
|
+
@base_block = block
|
84
|
+
end
|
85
|
+
|
86
|
+
def defaults(&block)
|
87
|
+
@defaults = block.call.freeze
|
88
|
+
end
|
89
|
+
|
90
|
+
def variants(&block)
|
91
|
+
@variants = VariantBuilder.new(true).build(&block)
|
92
|
+
end
|
93
|
+
|
94
|
+
def compile(**variants)
|
95
|
+
acc = Array(@base_block&.call || [])
|
96
|
+
|
97
|
+
@defaults.merge(variants.compact).each do |variant, value|
|
98
|
+
variant = @variants.dig(variant, value) || next
|
99
|
+
styles = variant.is_a?(::Proc) ? variant.call : variant
|
100
|
+
acc.concat(Array(styles))
|
101
|
+
end
|
102
|
+
|
103
|
+
acc
|
104
|
+
end
|
105
|
+
|
106
|
+
def dup
|
107
|
+
copy = super
|
108
|
+
copy.instance_variable_set(:@defaults, @defaults.dup)
|
109
|
+
copy.instance_variable_set(:@variants, @variants.dup)
|
110
|
+
copy
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class StyleConfig # :nodoc:
|
115
|
+
DEFAULT_POST_PROCESSOR = ->(compiled) { compiled.join(" ") }
|
116
|
+
|
117
|
+
attr_reader :postprocessor
|
118
|
+
|
119
|
+
def initialize
|
120
|
+
@styles = {}
|
121
|
+
@postprocessor = DEFAULT_POST_PROCESSOR
|
122
|
+
end
|
123
|
+
|
124
|
+
def define(name, &block)
|
125
|
+
styles[name] = StyleSet.new(&block)
|
126
|
+
end
|
127
|
+
|
128
|
+
def compile(name, **variants)
|
129
|
+
styles[name]&.compile(**variants).then do |compiled|
|
130
|
+
next unless compiled
|
131
|
+
|
132
|
+
postprocess(compiled)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Allow defining a custom postprocessor
|
137
|
+
def postprocess_with(callable = nil, &block)
|
138
|
+
@postprocessor = callable || block
|
139
|
+
end
|
140
|
+
|
141
|
+
def dup
|
142
|
+
copy = super
|
143
|
+
copy.instance_variable_set(:@styles, @styles.dup)
|
144
|
+
copy
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
attr_reader :styles
|
150
|
+
|
151
|
+
def postprocess(compiled) = postprocessor.call(compiled)
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.included(base)
|
155
|
+
base.extend ClassMethods
|
156
|
+
end
|
157
|
+
|
158
|
+
module ClassMethods
|
159
|
+
# Returns the name of the default style set based on the class name:
|
160
|
+
# MyComponent::Component => my_component
|
161
|
+
# Namespaced::MyComponent => my_component
|
162
|
+
def default_style_name
|
163
|
+
@default_style_name ||= name.demodulize.sub(/(::Component|Component)$/, "").underscore.presence || "component"
|
164
|
+
end
|
165
|
+
|
166
|
+
def style(name = default_style_name, &block)
|
167
|
+
style_config.define(name.to_sym, &block)
|
168
|
+
end
|
169
|
+
|
170
|
+
def style_config
|
171
|
+
@style_config ||=
|
172
|
+
if superclass.respond_to?(:style_config)
|
173
|
+
superclass.style_config.dup
|
174
|
+
else
|
175
|
+
StyleConfig.new
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def style(name = self.class.default_style_name, **variants)
|
181
|
+
self.class.style_config.compile(name.to_sym, **variants)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -11,6 +11,7 @@ module ViewComponentContrib
|
|
11
11
|
autoload :TranslationHelper, "view_component_contrib/translation_helper"
|
12
12
|
autoload :WrapperComponent, "view_component_contrib/wrapper_component"
|
13
13
|
autoload :WrappedHelper, "view_component_contrib/wrapped_helper"
|
14
|
+
autoload :StyleVariants, "view_component_contrib/style_variants"
|
14
15
|
|
15
16
|
autoload :Base, "view_component_contrib/base"
|
16
17
|
autoload :Preview, "view_component_contrib/preview"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_component-contrib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Dementyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: view_component
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.15.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: 0.15.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,6 +156,7 @@ files:
|
|
156
156
|
- lib/view_component_contrib/preview/default_template.rb
|
157
157
|
- lib/view_component_contrib/preview/sidecarable.rb
|
158
158
|
- lib/view_component_contrib/railtie.rb
|
159
|
+
- lib/view_component_contrib/style_variants.rb
|
159
160
|
- lib/view_component_contrib/translation_helper.rb
|
160
161
|
- lib/view_component_contrib/version.rb
|
161
162
|
- lib/view_component_contrib/wrapped_helper.rb
|
@@ -177,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
177
178
|
requirements:
|
178
179
|
- - ">="
|
179
180
|
- !ruby/object:Gem::Version
|
180
|
-
version: '2.
|
181
|
+
version: '2.7'
|
181
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
183
|
requirements:
|
183
184
|
- - ">="
|