view_component-contrib 0.2.2 → 0.2.3

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: eb40fc2b6095e17a5cb7402bb9c577ee9df9152b65342a3fd2879861b0ec61c4
4
- data.tar.gz: da852768b8dfe7907aae80bcee8afb5a52998185365e4f2bf702d2e5160df8cf
3
+ metadata.gz: e77986cf3606cd3c99d8bb42308ea152a0d2795d5e1f1976a047b46fc536ff17
4
+ data.tar.gz: 92cd0f179bdff4b3526ff93bd760116071c23ccff4c1693b772fbd93bfe3eb62
5
5
  SHA512:
6
- metadata.gz: d8492733e339fe678625730a079a5831c3647f9063aa13f50f3ef34d1a4c03a1505c536f06bb9cf3959310e311774b265c18cb9f01070d77b3d93a0e7b295241
7
- data.tar.gz: d6e0426d3014ea7978eaf807e9a8aa11b0d729f16309e303c2a6a2d0d2d09d34d9e2146293648b57aba7bece138c831f4182c983aea4c2602dfa3dcc769f0cf3
6
+ metadata.gz: 2719170e4c8a3b4f721f04cc7450302b10ac8fdc66046299921942d59a63dc1063e229f17657821b0b8879ced4d8ac0e968814fb527e0d5d8d9571ca507fa88f
7
+ data.tar.gz: 9b3f4ce732f3fd73668dfc70d15a80a2f96a52c5593ad6a2150e8df3e25234e9593c2d5d4cda39d2f0bd0e9f08e9958e290b7fb887541140fc3e2bc9d0f57e0e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.2.3 (2024-07-31)
6
+
7
+ - Fix publishing transpiled files (and bring Ruby 2.7 support back) ([@palkan][])
8
+
5
9
  ## 0.2.2 (2023-11-29)
6
10
 
7
11
  - Add `compound` styles support. ([@palkan][])
@@ -0,0 +1,211 @@
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
+ @compounds = {}
79
+
80
+ instance_eval(&init_block) if init_block
81
+ end
82
+
83
+ def base(&block)
84
+ @base_block = block
85
+ end
86
+
87
+ def defaults(&block)
88
+ @defaults = block.call.freeze
89
+ end
90
+
91
+ def variants(&block)
92
+ @variants = VariantBuilder.new(true).build(&block)
93
+ end
94
+
95
+ def compound(**variants, &block)
96
+ @compounds[variants] = block
97
+ end
98
+
99
+ def compile(**variants)
100
+ acc = Array(@base_block&.call || [])
101
+
102
+ config = @defaults.merge(variants.compact)
103
+
104
+ config.each do |variant, value|
105
+ value = cast_value(value)
106
+ variant = @variants.dig(variant, value) || next
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
115
+ acc.concat(Array(styles))
116
+ end
117
+
118
+ acc
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
139
+ end
140
+
141
+ class StyleConfig # :nodoc:
142
+ DEFAULT_POST_PROCESSOR = ->(compiled) { compiled.join(" ") }
143
+
144
+ attr_reader :postprocessor
145
+
146
+ def initialize
147
+ @styles = {}
148
+ @postprocessor = DEFAULT_POST_PROCESSOR
149
+ end
150
+
151
+ def define(name, &block)
152
+ styles[name] = StyleSet.new(&block)
153
+ end
154
+
155
+ def compile(name, **variants)
156
+ styles[name]&.compile(**variants).then do |compiled|
157
+ next unless compiled
158
+
159
+ postprocess(compiled)
160
+ end
161
+ end
162
+
163
+ # Allow defining a custom postprocessor
164
+ def postprocess_with(callable = nil, &block)
165
+ @postprocessor = callable || block
166
+ end
167
+
168
+ def dup
169
+ copy = super
170
+ copy.instance_variable_set(:@styles, @styles.dup)
171
+ copy
172
+ end
173
+
174
+ private
175
+
176
+ attr_reader :styles
177
+
178
+ def postprocess(compiled) ; postprocessor.call(compiled); end
179
+ end
180
+
181
+ def self.included(base)
182
+ base.extend ClassMethods
183
+ end
184
+
185
+ module ClassMethods
186
+ # Returns the name of the default style set based on the class name:
187
+ # MyComponent::Component => my_component
188
+ # Namespaced::MyComponent => my_component
189
+ def default_style_name
190
+ @default_style_name ||= name.demodulize.sub(/(::Component|Component)$/, "").underscore.presence || "component"
191
+ end
192
+
193
+ def style(name = default_style_name, &block)
194
+ style_config.define(name.to_sym, &block)
195
+ end
196
+
197
+ def style_config
198
+ @style_config ||=
199
+ if superclass.respond_to?(:style_config)
200
+ superclass.style_config.dup
201
+ else
202
+ StyleConfig.new
203
+ end
204
+ end
205
+ end
206
+
207
+ def style(name = self.class.default_style_name, **variants)
208
+ self.class.style_config.compile(name.to_sym, **variants)
209
+ end
210
+ end
211
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ViewComponentContrib # :nodoc:all
4
- VERSION = "0.2.2"
4
+ VERSION = "0.2.3"
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.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-29 00:00:00.000000000 Z
11
+ date: 2024-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: view_component
@@ -147,6 +147,7 @@ files:
147
147
  - LICENSE.txt
148
148
  - README.md
149
149
  - app/views/view_component_contrib/preview.html.erb
150
+ - lib/.rbnext/3.0/view_component_contrib/style_variants.rb
150
151
  - lib/view_component-contrib.rb
151
152
  - lib/view_component_contrib.rb
152
153
  - lib/view_component_contrib/base.rb
@@ -170,7 +171,7 @@ metadata:
170
171
  documentation_uri: http://github.com/palkan/view_component-contrib
171
172
  homepage_uri: http://github.com/palkan/view_component-contrib
172
173
  source_code_uri: http://github.com/palkan/view_component-contrib
173
- post_install_message:
174
+ post_install_message:
174
175
  rdoc_options: []
175
176
  require_paths:
176
177
  - lib
@@ -185,8 +186,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
186
  - !ruby/object:Gem::Version
186
187
  version: '0'
187
188
  requirements: []
188
- rubygems_version: 3.4.20
189
- signing_key:
189
+ rubygems_version: 3.4.19
190
+ signing_key:
190
191
  specification_version: 4
191
192
  summary: A collection of extensions and developer tools for ViewComponent
192
193
  test_files: []