class_variants 1.0.0 → 1.1.0

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