view_component-contrib 0.2.1 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b586c9ad03730cff1cc38721c6904f427c71a73f5777605f17fc0379f60f8dc7
4
- data.tar.gz: 7c2ed9aed5c845492a8487fab7ce5e66c639d455d8b4027c383b047ad961fdf0
3
+ metadata.gz: eb40fc2b6095e17a5cb7402bb9c577ee9df9152b65342a3fd2879861b0ec61c4
4
+ data.tar.gz: da852768b8dfe7907aae80bcee8afb5a52998185365e4f2bf702d2e5160df8cf
5
5
  SHA512:
6
- metadata.gz: c1d2f760734b6ca7f71da538fbba4c04b0ff91b885cc47e09f3943b81a5a097ef62293348dc3ac07e20a4b812e52cf8a4bd8b39b6cb306551dceac4a784c652b
7
- data.tar.gz: baaf5f34009ca87228246f260357339849f3d22e988543f36c36e772293bede4f249741fee5749db46d37a78dd8dc94674e13181d618282463a31afd5dba48b7
6
+ metadata.gz: d8492733e339fe678625730a079a5831c3647f9063aa13f50f3ef34d1a4c03a1505c536f06bb9cf3959310e311774b265c18cb9f01070d77b3d93a0e7b295241
7
+ data.tar.gz: d6e0426d3014ea7978eaf807e9a8aa11b0d729f16309e303c2a6a2d0d2d09d34d9e2146293648b57aba7bece138c831f4182c983aea4c2602dfa3dcc769f0cf3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
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
+
5
11
  ## 0.2.1 (2023-11-16)
6
12
 
7
13
  - Fix style variants inhertiance. ([@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,58 @@ 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
+
284
341
  ### Using with TailwindCSS LSP
285
342
 
286
343
  To make completions (and other LSP features) work with our DSL, try the following configuration:
@@ -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,12 +92,26 @@ 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
 
@@ -107,8 +122,20 @@ module ViewComponentContrib
107
122
  copy = super
108
123
  copy.instance_variable_set(:@defaults, @defaults.dup)
109
124
  copy.instance_variable_set(:@variants, @variants.dup)
125
+ copy.instance_variable_set(:@compounds, @compounds.dup)
110
126
  copy
111
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
112
139
  end
113
140
 
114
141
  class StyleConfig # :nodoc:
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ViewComponentContrib # :nodoc:all
4
- VERSION = "0.2.1"
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.1
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-16 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