view_component-contrib 0.2.2 → 0.2.3

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: 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: []