class_variants 1.0.0 → 1.1.0

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: 0c8fd556b85ee91d2d2709e66af72e1d4017c5a20ba5884c49eed0c755f1a593
4
- data.tar.gz: c6f77333c70953510eb23ab94846c2b2f9d1ae1a8b185c289ee3530060546651
3
+ metadata.gz: ffcbc4e2fd078ac3b22bd391226eec4fc4429bcee10237613f1736bfcff08b6f
4
+ data.tar.gz: 4101b943cfd16a259d52e978c3081788451fcd1336ae44644b027aeebb1a4f34
5
5
  SHA512:
6
- metadata.gz: c9f77343da5f6e521cd8a895cef3683a5fc65823b8df3f1f84d03adf38099fb6f51cfc191e24111d35f7ac95ef697e6a61b6dc37a547c50b4732e0863e78631f
7
- data.tar.gz: 5a0db3c1db7f88ccc689fbaadc514aa04d73ef405e1ae05755a55918d16d1f1179ff9c736b11402da99e57917c393fd830801f6d78b87c07964d9dc951ac3f98
6
+ metadata.gz: 3dd5e798a846188944d4fe74342414ccfa180ba6fa319a0e1f2b0ab775f4c32c4d0a5c1129a42c52dce44765cd981db20b5a222b6605989ade32e39a7693fb5f
7
+ data.tar.gz: e3eb94faf2f8ad63b6d96fe322b274c77e8a4b2e9fcc2123e267d2b6580398fd06122b73841dbd1a1aea9709667b1afec8ab8c3bce3eecfb4db7e6d409907a76
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022 Adrian Marin
3
+ Copyright (c) 2025 Adrian Marin
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,8 +1,8 @@
1
1
  module ClassVariants
2
2
  module ActionView
3
3
  module Helpers
4
- def class_variants(classes, **args)
5
- ClassVariants::Instance.new classes, **args
4
+ def class_variants(...)
5
+ ClassVariants::Instance.new(...)
6
6
  end
7
7
  end
8
8
  end
@@ -2,22 +2,22 @@ module ClassVariants
2
2
  module Helper
3
3
  module ClassMethods
4
4
  def class_variants(...)
5
- @_class_variants_instance = ClassVariants.build(...)
6
- end
7
-
8
- def _class_variants_instance
9
- @_class_variants_instance
5
+ singleton_class.instance_variable_get(:@_class_variants_instance).merge(...)
10
6
  end
11
7
  end
12
8
 
13
9
  def self.included(base)
14
10
  base.extend(ClassMethods)
11
+ base.singleton_class.instance_variable_set(:@_class_variants_instance, ClassVariants::Instance.new)
12
+ base.define_singleton_method(:inherited) do |subclass|
13
+ subclass.singleton_class.instance_variable_set(
14
+ :@_class_variants_instance, base.singleton_class.instance_variable_get(:@_class_variants_instance).dup
15
+ )
16
+ end
15
17
  end
16
18
 
17
19
  def class_variants(...)
18
- raise "You must configure class_variants in class definition" unless self.class._class_variants_instance
19
-
20
- self.class._class_variants_instance.render(...)
20
+ self.class.singleton_class.instance_variable_get(:@_class_variants_instance).render(...)
21
21
  end
22
22
  end
23
23
  end
@@ -1,20 +1,44 @@
1
1
  module ClassVariants
2
2
  class Instance
3
- def initialize(**options, &block)
3
+ def initialize(...)
4
+ @bases = []
5
+ @variants = []
6
+ @defaults = {}
7
+
8
+ merge(...)
9
+ end
10
+
11
+ def dup
12
+ self.class.new.tap do |copy|
13
+ copy.instance_variable_set(:@bases, @bases.dup)
14
+ copy.instance_variable_set(:@variants, @variants.dup)
15
+ copy.instance_variable_set(:@defaults, @defaults.dup)
16
+ end
17
+ end
18
+
19
+ def merge(**options, &block)
4
20
  raise ArgumentError, "Use of hash config and code block is not supported" if !options.empty? && block_given?
5
21
 
6
- @base = options.empty? ? {} : {default: options.fetch(:base, nil)}
7
- @variants = expand_variants(options.fetch(:variants, {})) + expand_compound_variants(options.fetch(:compound_variants, []))
8
- @defaults = options.fetch(:defaults, {})
22
+ (base = options.fetch(:base, nil)) && @bases << {class: base, slot: :default}
23
+ @variants += [
24
+ expand_variants(options.fetch(:variants, {})),
25
+ expand_compound_variants(options.fetch(:compound_variants, []))
26
+ ].inject(:+)
27
+ @defaults.merge!(options.fetch(:defaults, {}))
9
28
 
10
29
  instance_eval(&block) if block_given?
30
+
31
+ self
11
32
  end
12
33
 
13
34
  def render(slot = :default, **overrides)
14
35
  classes = overrides.delete(:class)
36
+ result = []
15
37
 
16
38
  # Start with our default classes
17
- result = [@base[slot]]
39
+ @bases.each do |base|
40
+ result << base[:class] if base[:slot] == slot
41
+ end
18
42
 
19
43
  # Then merge the passed in overrides on top of the defaults
20
44
  criteria = @defaults.merge(overrides)
@@ -44,10 +68,10 @@ module ClassVariants
44
68
 
45
69
  if block_given?
46
70
  with_slots(&block).each do |slot|
47
- @base[slot[:slot]] = slot[:class]
71
+ @bases << slot
48
72
  end
49
73
  else
50
- @base[:default] = klass
74
+ @bases << {slot: :default, class: klass}
51
75
  end
52
76
  end
53
77
 
@@ -1,3 +1,3 @@
1
1
  module ClassVariants
2
- VERSION = "1.0.0".freeze
2
+ VERSION = "1.1.0".freeze
3
3
  end
data/readme.md CHANGED
@@ -8,7 +8,6 @@ Inspired by [variant-classnames](https://github.com/mattvalleycodes/variant-clas
8
8
 
9
9
  * [DRY up your tailwind CSS using this awesome gem](https://www.youtube.com/watch?v=cFcwNH6x77g)
10
10
 
11
-
12
11
  ## Installation
13
12
 
14
13
  Add this line to your application's Gemfile:
@@ -34,9 +33,9 @@ $ gem install class_variants
34
33
  We create an object from the class or helper where we define the configuration using four arguments:
35
34
 
36
35
  1. The `base` keyword argument with default classes that should be applied to each variant.
37
- 1. The `variants` keyword argument where we declare the variants with their option and classes.
38
- 1. The `compound_variants` keyword argument where we declare the compound variants with their conditions and classes
39
- 1. The `defaults` keyword argument (optional) where we declare the default value for each variant.
36
+ 2. The `variants` keyword argument where we declare the variants with their option and classes.
37
+ 3. The `compound_variants` keyword argument where we declare the compound variants with their conditions and classes
38
+ 4. The `defaults` keyword argument (optional) where we declare the default value for each variant.
40
39
 
41
40
  Below we'll implement the [button component](https://tailwindui.com/components/application-ui/elements/buttons) from Tailwind UI.
42
41
 
@@ -185,6 +184,14 @@ end
185
184
  </div>
186
185
  ```
187
186
 
187
+ ## Merge definitions
188
+
189
+ ```ruby
190
+ alert_classes = ClassVariants.build(base: "bg-white")
191
+ alert_classes.merge(base: "text-black")
192
+ alert_classes.render # => "bg-white text-black"
193
+ ```
194
+
188
195
  ## Full API
189
196
 
190
197
  ```ruby
@@ -272,7 +279,7 @@ alert_classes.render(:body, class: "...")
272
279
 
273
280
  ```ruby
274
281
  # Somewhere in your helpers
275
- def button_classes(classes, **args)
282
+ def button_classes
276
283
  class_variants(
277
284
  base: "inline-flex items-center rounded border border-transparent font-medium text-white hover:text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2",
278
285
  variants: {
@@ -303,6 +310,10 @@ end
303
310
  <%= link_to :Avo, "https://avohq.io", class: button_classes.render(color: :red, size: :xl) %>
304
311
  ```
305
312
 
313
+ ### Output
314
+
315
+ ### ![](sample.jpg)
316
+
306
317
  ## Helper module
307
318
 
308
319
  If you're developing something more complex you might want to use composition more. You might want to use the helper module for that.
@@ -311,19 +322,43 @@ If you're developing something more complex you might want to use composition mo
311
322
  class MyClass
312
323
  include ClassVariants::Helper
313
324
 
314
- class_variants {
315
- base: {},
316
- variants: {}
317
- }
325
+ class_variants(
326
+ base: "bg-white",
327
+ variants: {
328
+ color: {
329
+ red: "text-red",
330
+ blue: "text-blue"
331
+ }
332
+ }
333
+ )
318
334
  end
319
335
 
320
- MyClass.new.class_variants(:container, color: :red, class: "shadow")
336
+ MyClass.new.class_variants(color: :red, class: "shadow") # => "bg-white text-red shadow"
337
+ ```
338
+
339
+ This helper supports class inheritance, so that the subclass receives a copy of the class_variants config that the parent class had at the time of inheritance. From that point on, the settings are kept separate for both. Successive calls to class_variants helper method, will cause the configuration to be merged.
340
+
341
+ ```ruby
342
+ class A
343
+ include ClassVariants::Helper
344
+
345
+ class_variants(base: "bg-red")
346
+ end
347
+
348
+ class B < A
349
+ class_variants(base: "text-black")
350
+ end
351
+
352
+ A.class_variants(base: "text-white")
353
+
354
+ A.new.class_variants # => "bg-red text-white"
355
+ B.new.class_variants # => "bg-red text-black"
321
356
  ```
322
357
 
323
358
  ## `tailwind_merge`
324
359
 
325
360
  By default, the classes are merged using `concat`, but you can use the awesome [TailwindMerge](https://github.com/gjtorikian/tailwind_merge) gem.
326
- Install the gem using `bundle add tailwind_merge` and use this configuration to enable it.
361
+ Install the gem using `bundle add tailwind_merge` and use this configuration to enable it. If you're using Rails, you can put this in an initializer.
327
362
 
328
363
  ```ruby
329
364
  ClassVariants.configure do |config|
@@ -333,16 +368,12 @@ ClassVariants.configure do |config|
333
368
  end
334
369
  ```
335
370
 
336
- ### Output
337
-
338
- ![](sample.jpg)
339
-
340
371
  ## Other packages
341
372
 
342
- - [`active_storage-blurhash`](https://github.com/avo-hq/active_storage-blurhash) - A plug-n-play [blurhash](https://blurha.sh/) integration for images stored in ActiveStorage
343
- - [`avo`](https://github.com/avo-hq/avo) - Build Content management systems with Ruby on Rails
344
- - [`prop_initializer`](https://github.com/avo-hq/prop_initializer) - A flexible tool for defining properties on Ruby classes.
345
- - [`stimulus-confetti`](https://github.com/avo-hq/stimulus-confetti) - The easiest way to add confetti to your StimulusJS app
373
+ - [`active_storage-blurhash`](https://github.com/avo-hq/active_storage-blurhash) - A plug-n-play [blurhash](https://blurha.sh/) integration for images stored in ActiveStorage
374
+ - [`avo`](https://github.com/avo-hq/avo) - Build Content management systems with Ruby on Rails
375
+ - [`prop_initializer`](https://github.com/avo-hq/prop_initializer) - A flexible tool for defining properties on Ruby classes.
376
+ - [`stimulus-confetti`](https://github.com/avo-hq/stimulus-confetti) - The easiest way to add confetti to your StimulusJS app
346
377
 
347
378
  ## Try Avo ⭐️
348
379
 
@@ -353,12 +384,13 @@ If you enjoyed this gem try out [Avo](https://github.com/avo-hq/avo). It helps d
353
384
  ## Contributing
354
385
 
355
386
  1. Fork it `git clone https://github.com/avo-hq/class_variants`
356
- 1. Create your feature branch `git checkout -b my-new-feature`
357
- 1. Commit your changes `git commit -am 'Add some feature'`
358
- 1. Push to the branch `git push origin my-new-feature`
359
- 1. Create new Pull Request
387
+ 2. Create your feature branch `git checkout -b my-new-feature`
388
+ 3. Commit your changes `git commit -am 'Add some feature'`
389
+ 4. Push to the branch `git push origin my-new-feature`
390
+ 5. Create new Pull Request
360
391
 
361
392
  ## License
393
+
362
394
  This package is available as open source under the terms of the MIT License.
363
395
 
364
396
  ## Cutting a release
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: class_variants
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-13 00:00:00.000000000 Z
11
+ date: 2025-01-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Easily configure styles and apply them as classes.
14
14
  email: adrian@adrianthedev.com