view_component-contrib 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 814046bee78131bac6659eaa62160b6dfef169d48d1c5850c03dbe6a00a2ad0f
4
- data.tar.gz: ef1ec7cfb3f71bf4db995be3a564dcfc0ff04e72d3c4e116515d216de18b38e8
3
+ metadata.gz: eb40fc2b6095e17a5cb7402bb9c577ee9df9152b65342a3fd2879861b0ec61c4
4
+ data.tar.gz: da852768b8dfe7907aae80bcee8afb5a52998185365e4f2bf702d2e5160df8cf
5
5
  SHA512:
6
- metadata.gz: 9a5d578dfc44e7318da343a0aefe65946cce2399675d92646fd33db8e7494040d16433a3c409a08185d04c249fbc538e494175dce593a6bde19e27d254926d42
7
- data.tar.gz: d01e0bf7f11d866aaab42dafb040e7ee45e4257524888b7bb6768b399d2db03c971867e6b14d839c1a66f7e37d9fe71982e287c8280b3a16811891bc61ee4723
6
+ metadata.gz: d8492733e339fe678625730a079a5831c3647f9063aa13f50f3ef34d1a4c03a1505c536f06bb9cf3959310e311774b265c18cb9f01070d77b3d93a0e7b295241
7
+ data.tar.gz: d6e0426d3014ea7978eaf807e9a8aa11b0d729f16309e303c2a6a2d0d2d09d34d9e2146293648b57aba7bece138c831f4182c983aea4c2602dfa3dcc769f0cf3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.2.2 (2023-11-29)
6
+
7
+ - Add `compound` styles support. ([@palkan][])
8
+
9
+ - Support using booleans as style variant values. ([@palkan][])
10
+
11
+ ## 0.2.1 (2023-11-16)
12
+
13
+ - Fix style variants inhertiance. ([@palkan][])
14
+
5
15
  ## 0.2.0 (2023-11-07)
6
16
 
7
17
  - Introduce style variants. ([@palkan][])
data/README.md CHANGED
@@ -209,15 +209,19 @@ class ButtonComponent < ViewComponent::Base
209
209
  md { "text-base" }
210
210
  lg { "px-4 py-3 text-lg" }
211
211
  }
212
+ disabled {
213
+ yes { "opacity-75" }
214
+ }
212
215
  }
213
216
  defaults { {size: :md, color: :primary} }
214
217
  end
215
218
 
216
- attr_reader :size, :color
219
+ attr_reader :size, :color, :disabled
217
220
 
218
- def initialize(size: nil, color: nil)
221
+ def initialize(size: nil, color: nil, disabled: false)
219
222
  @size = size
220
223
  @color = color
224
+ @disabled = disabled
221
225
  end
222
226
  end
223
227
  ```
@@ -234,6 +238,12 @@ Passing `size: :lg` and `color: :secondary` would result in the following HTML:
234
238
  <button class="font-medium bg-purple-500 text-white rounded-full px-4 py-3 text-lg">Click me</button>
235
239
  ```
236
240
 
241
+ The `true` / `false` variant value would be converted into the `yes` / `no` variants:
242
+
243
+ ```erb
244
+ <button class="<%= style(size:, color:, disabled: true) %>">Click me</button>
245
+ ```
246
+
237
247
  **NOTE:** If you pass `nil`, the default value would be used.
238
248
 
239
249
  You can define multiple style sets in a single component:
@@ -276,11 +286,74 @@ class ButtonComponent < ViewComponent::Base
276
286
  # You can provide either a proc or any other callable object
277
287
  style_config.postprocess_with do |classes|
278
288
  # classes is an array of CSS classes
289
+ # NOTE: This is an abstract TailwindMerge class, not to be confused with existing libraries
279
290
  TailwindMerge.call(classes).join(" ")
280
291
  end
281
292
  end
282
293
  ```
283
294
 
295
+ ### Dependent (or compound) styles
296
+
297
+ Sometimes it might be necessary to define complex styling rules, e.g., when a combination of variants requires adding additional styles. That's where usage of Ruby blocks for configuration becomes useful. For example:
298
+
299
+ ```ruby
300
+ style do
301
+ variants {
302
+ size {
303
+ sm { "text-sm" }
304
+ md { "text-base" }
305
+ lg { "px-4 py-3 text-lg" }
306
+ }
307
+ theme {
308
+ primary do |size:, **|
309
+ %w[bg-blue-500 text-white].tap do
310
+ _1 << "uppercase" if size == :lg
311
+ end
312
+ end
313
+ secondary { %w[bg-purple-500 text-white] }
314
+ }
315
+ }
316
+ end
317
+ ```
318
+
319
+ The specified variants are passed as block arguments, so you can implement dynamic styling.
320
+
321
+ If you prefer declarative approach, you can use the special `compound` directive. The previous example could be rewritten as follows:
322
+
323
+ ```ruby
324
+ style do
325
+ variants {
326
+ size {
327
+ sm { "text-sm" }
328
+ md { "text-base" }
329
+ lg { "px-4 py-3 text-lg" }
330
+ }
331
+ theme {
332
+ primary { %w[bg-blue-500 text-white] }
333
+ secondary { %w[bg-purple-500 text-white] }
334
+ }
335
+ }
336
+
337
+ compound(size: :lg, theme: :primary) { %w[uppercase] }
338
+ end
339
+ ```
340
+
341
+ ### Using with TailwindCSS LSP
342
+
343
+ To make completions (and other LSP features) work with our DSL, try the following configuration:
344
+
345
+ ```json
346
+ "tailwindCSS.includeLanguages": {
347
+ "erb": "html",
348
+ "ruby": "html"
349
+ },
350
+ "tailwindCSS.experimental.classRegex": [
351
+ "%w\\[([^\\]]*)\\]"
352
+ ]
353
+ ```
354
+
355
+ **NOTE:** It will only work with `%w[ ... ]` word arrays, but you can adjust it to your needs.
356
+
284
357
  ## Organizing assets (JS, CSS)
285
358
 
286
359
  **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.
@@ -75,6 +75,7 @@ module ViewComponentContrib
75
75
  @base_block = nil
76
76
  @defaults = {}
77
77
  @variants = {}
78
+ @compounds = {}
78
79
 
79
80
  instance_eval(&init_block) if init_block
80
81
  end
@@ -91,17 +92,50 @@ module ViewComponentContrib
91
92
  @variants = VariantBuilder.new(true).build(&block)
92
93
  end
93
94
 
95
+ def compound(**variants, &block)
96
+ @compounds[variants] = block
97
+ end
98
+
94
99
  def compile(**variants)
95
100
  acc = Array(@base_block&.call || [])
96
101
 
97
- @defaults.merge(variants.compact).each do |variant, value|
102
+ config = @defaults.merge(variants.compact)
103
+
104
+ config.each do |variant, value|
105
+ value = cast_value(value)
98
106
  variant = @variants.dig(variant, value) || next
99
- styles = variant.is_a?(::Proc) ? variant.call : variant
107
+ styles = variant.is_a?(::Proc) ? variant.call(**config) : variant
108
+ acc.concat(Array(styles))
109
+ end
110
+
111
+ @compounds.each do |compound, value|
112
+ next unless compound.all? { |k, v| config[k] == v }
113
+
114
+ styles = value.is_a?(::Proc) ? value.call(**config) : value
100
115
  acc.concat(Array(styles))
101
116
  end
102
117
 
103
118
  acc
104
119
  end
120
+
121
+ def dup
122
+ copy = super
123
+ copy.instance_variable_set(:@defaults, @defaults.dup)
124
+ copy.instance_variable_set(:@variants, @variants.dup)
125
+ copy.instance_variable_set(:@compounds, @compounds.dup)
126
+ copy
127
+ end
128
+
129
+ private
130
+
131
+ def cast_value(val)
132
+ case val
133
+ when true then :yes
134
+ when false then :no
135
+ else
136
+ val
137
+ end
138
+ end
105
139
  end
106
140
 
107
141
  class StyleConfig # :nodoc:
@@ -131,6 +165,12 @@ module ViewComponentContrib
131
165
  @postprocessor = callable || block
132
166
  end
133
167
 
168
+ def dup
169
+ copy = super
170
+ copy.instance_variable_set(:@styles, @styles.dup)
171
+ copy
172
+ end
173
+
134
174
  private
135
175
 
136
176
  attr_reader :styles
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ViewComponentContrib # :nodoc:all
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.2"
5
5
  end
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.2.0
4
+ version: 0.2.2
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-08 00:00:00.000000000 Z
11
+ date: 2023-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: view_component