Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for merging #23

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## Unreleased
- Add support for merging ([#23](https://github.com/avo-hq/class_variants/pull/23))

## 1.0.0 (2024-11-13)
- Add support for slots ([#15](https://github.com/avo-hq/class_variants/pull/15))
- Allow passing additional classes when render ([#17](https://github.com/avo-hq/class_variants/pull/17))
Expand Down
30 changes: 23 additions & 7 deletions lib/class_variants/instance.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
module ClassVariants
class Instance
def initialize(**options, &block)
def initialize(...)
@bases = []
@variants = []
@defaults = {}

merge(...)
end

def merge(**options, &block)
raise ArgumentError, "Use of hash config and code block is not supported" if !options.empty? && block_given?

@base = options.empty? ? {} : {default: options.fetch(:base, nil)}
@variants = expand_variants(options.fetch(:variants, {})) + expand_compound_variants(options.fetch(:compound_variants, []))
@defaults = options.fetch(:defaults, {})
(base = options.fetch(:base, nil)) && @bases << {class: base, slot: :default}
@variants += [
expand_variants(options.fetch(:variants, {})),
expand_compound_variants(options.fetch(:compound_variants, []))
].inject(:+)
@defaults.merge!(options.fetch(:defaults, {}))

instance_eval(&block) if block_given?

self
end

def render(slot = :default, **overrides)
classes = overrides.delete(:class)
result = []

# Start with our default classes
result = [@base[slot]]
@bases.each do |base|
result << base[:class] if base[:slot] == slot
end

# Then merge the passed in overrides on top of the defaults
criteria = @defaults.merge(overrides)
Expand Down Expand Up @@ -44,10 +60,10 @@ def base(klass = nil, &block)

if block_given?
with_slots(&block).each do |slot|
@base[slot[:slot]] = slot[:class]
@bases << slot
end
else
@base[:default] = klass
@bases << {slot: :default, class: klass}
end
end

Expand Down
71 changes: 71 additions & 0 deletions test/merge_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
require "test_helper"

class MergeTest < Minitest::Test
def test_hash_merge
cv = ClassVariants.build(
base: "rounded",
variants: {
color: {
primary: "bg-blue-500",
secondary: "bg-purple-500",
success: "bg-green-500"
}
},
default: {
color: :primary
}
)
cv.merge(
base: "border",
variants: {
color: {
primary: "bg-blue-700",
secondary: "bg-purple-700"
}
},
defaults: {
color: :secondary
}
)

assert_equal "rounded border bg-purple-500 bg-purple-700", cv.render
end

def test_block_merge
cv = ClassVariants.build do
base do
slot :root, class: "rounded"
slot :title, class: "font-bold"
end

variant variant: :outlined do
slot :root, class: "border-red-700"
slot :title, class: "text-red-700"
end

variant variant: :filled do
slot :root, class: "bg-red-100"
slot :title, class: "text-red-900"
end

defaults variant: :outlined
end

cv.merge do
base do
slot :root, class: "mb-4"
slot :title, class: "mb-1"
end

variant variant: :filled do
slot :root, class: "dark:bg-red-800"
slot :title, class: "dark:text-red-50"
end

defaults variant: :filled
end

assert_equal "rounded mb-4 bg-red-100 dark:bg-red-800", cv.render(:root)
assert_equal "font-bold mb-1 text-red-900 dark:text-red-50", cv.render(:title)
end
end