Skip to content

Commit

Permalink
Extract AttributeSet and ClassList from Base
Browse files Browse the repository at this point in the history
  • Loading branch information
davidalejandroaguilar committed Aug 16, 2024
1 parent 7f38e3b commit b6e322e
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 78 deletions.
28 changes: 28 additions & 0 deletions lib/phlexy_ui/attribute_set.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module PhlexyUI
class AttributeSet
def initialize(base_modifiers, attributes_map)
@base_modifiers = base_modifiers
@attributes_map = attributes_map
end

def to_h
attributes_modifiers.each_with_object({}) do |modifier, final_attributes_hash|
value = attributes_map[modifier]

if value.is_a?(Hash)
final_attributes_hash.merge!(value)
elsif value
final_attributes_hash[modifier] = value
end
end
end

private

attr_reader :base_modifiers, :attributes_map

def attributes_modifiers
base_modifiers.select { |modifier| attributes_map.key?(modifier) }
end
end
end
47 changes: 8 additions & 39 deletions lib/phlexy_ui/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

module PhlexyUI
class Base < Phlex::HTML
RESPONSIVE_PREFIXES = %i[sm md lg].freeze

def initialize(*base_modifiers, **options)
@base_modifiers = base_modifiers
@options = options
Expand All @@ -19,47 +17,18 @@ def generate_classes!(
options: {},
modifiers_map: {}
)
[].then do |classes|
if component_html_class
classes << with_config_prefix(component_html_class)
end

classes.concat(html_classes_for_modifiers(base_modifiers, modifiers_map))
classes.concat(responsive_html_classes_for_modifiers!(options, modifiers_map))
classes << options.delete(:class) if options[:class]
ClassList.new(
component_html_class:,
base_modifiers:,
options:,
modifiers_map:
).to_a.then do |classes|
classes.any? ? classes : nil
end
end

def responsive_html_classes_for_modifiers!(options, modifiers_map)
options_to_responsive_modifiers_hash!(options).flat_map do |responsive_prefix, modifiers|
html_classes_for_modifiers(modifiers, modifiers_map, responsive_prefix:)
end
end

def options_to_responsive_modifiers_hash!(options)
RESPONSIVE_PREFIXES.to_h do |responsive_prefix|
[responsive_prefix, Array(options.delete(responsive_prefix))]
end
end

def html_classes_for_modifiers(modifiers, modifiers_map, responsive_prefix: nil)
modifiers.map do |modifier|
with_responsive_prefix(
with_config_prefix(modifiers_map.fetch(modifier)),
responsive_prefix:
)
end
rescue KeyError => e
raise ArgumentError, "Modifier `#{e.key}` is not defined for #{self.class}"
end

def with_config_prefix(string)
"#{PhlexyUI.configuration.prefix}#{string}"
end

def with_responsive_prefix(string, responsive_prefix: nil)
responsive_prefix ? "#{responsive_prefix}:#{string}" : string
def generate_attributes(base_modifiers, attributes_map)
AttributeSet.new(base_modifiers, attributes_map).to_h
end
end
end
75 changes: 75 additions & 0 deletions lib/phlexy_ui/class_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
module PhlexyUI
class ClassList
RESPONSIVE_PREFIXES = %i[sm md lg].freeze

def initialize(component_html_class: nil, base_modifiers: [], options: {}, modifiers_map: {})
@component_html_class = component_html_class
@base_modifiers = base_modifiers
@options = options
@modifiers_map = modifiers_map
end

def to_a
classes = []
add_component_class(classes)
add_base_classes(classes)
add_responsive_classes(classes)
add_additional_class(classes)
classes
end

private

attr_reader :component_html_class, :base_modifiers, :options, :modifiers_map

def classes_modifiers
base_modifiers.select { |modifier| modifiers_map.key?(modifier) }
end

def add_component_class(classes)
return unless component_html_class

classes << with_config_prefix(component_html_class)
end

def add_base_classes(classes)
classes.concat(html_classes_for_modifiers(classes_modifiers))
end

def html_classes_for_modifiers(modifiers, responsive_prefix: nil)
modifiers.map do |modifier|
with_responsive_prefix(
with_config_prefix(
modifiers_map.fetch(modifier)
),
responsive_prefix
)
end
end

def add_responsive_classes(classes)
RESPONSIVE_PREFIXES.each do |responsive_prefix|
if (values = options.delete(responsive_prefix))
classes.concat(
html_classes_for_modifiers(
Array(values),
responsive_prefix:
)
)
end
end
end

def add_additional_class(classes)
classes << options.delete(:class) if options[:class]
end

def with_config_prefix(string)
"#{PhlexyUI.configuration.prefix}#{string}"
end

def with_responsive_prefix(string, responsive_prefix = nil)
responsive_prefix ? "#{responsive_prefix}:#{string}" : string
end
end
end
4 changes: 1 addition & 3 deletions lib/phlexy_ui/collapsible_sub_menu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ def initialize(*, **)
end

def view_template(&)
attributes = ATTRIBUTES_MAP.select do |key|
base_modifiers.include?(key)
end
attributes = generate_attributes(base_modifiers, ATTRIBUTES_MAP)

details(**attributes) do
if @title
Expand Down
20 changes: 8 additions & 12 deletions lib/phlexy_ui/tab_with_content.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "debug"

module PhlexyUI
# @private
class TabWithContent < Base
Expand All @@ -13,17 +15,10 @@ def initialize(*base_modifiers, content:, id: nil, **)
def view_template(&)
title, *base_modifiers = @base_modifiers

@attributes_modifiers = base_modifiers.select do |modifier|
ATTRIBUTES_MAP.key?(modifier)
end

base_modifiers = base_modifiers.reject do |modifier|
ATTRIBUTES_MAP.key?(modifier)
end

attributes = ATTRIBUTES_MAP.select do |key|
@attributes_modifiers.include?(key)
end
attributes = generate_attributes(
base_modifiers,
ATTRIBUTES_MAP
)

generate_classes!(
component_html_class: :tab,
Expand All @@ -50,7 +45,8 @@ def view_template(&)
attr_reader :title

ATTRIBUTES_MAP = {
checked: true
open: {checked: true},
closed: true
}.freeze
end
end
7 changes: 2 additions & 5 deletions spec/lib/phlexy_ui/button_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,9 @@
end

context "when modifier doesn't exist" do
it "raises an error" do
it "does not raise an error" do
expect { render described_class.new(:foo) }
.to raise_error(
ArgumentError,
"Modifier `foo` is not defined for PhlexyUI::Button"
)
.not_to raise_error
end
end

Expand Down
7 changes: 2 additions & 5 deletions spec/lib/phlexy_ui/card_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,9 @@
end

context "when condition doesn't exist" do
it "raises an error" do
it "does not raise an error" do
expect { render described_class.new(:foo) }
.to raise_error(
ArgumentError,
"Modifier `foo` is not defined for PhlexyUI::Card"
)
.not_to raise_error
end
end

Expand Down
5 changes: 1 addition & 4 deletions spec/lib/phlexy_ui/drawer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
context "when condition doesn't exist" do
it "raises an error" do
expect { render described_class.new(:foo, id: :my_drawer) }
.to raise_error(
ArgumentError,
"Modifier `foo` is not defined for PhlexyUI::Drawer"
)
.not_to raise_error
end
end

Expand Down
5 changes: 1 addition & 4 deletions spec/lib/phlexy_ui/menu_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@
context "when condition doesn't exist" do
it "raises an error" do
expect { render described_class.new(:foo) }
.to raise_error(
ArgumentError,
"Modifier `foo` is not defined for PhlexyUI::Menu"
)
.not_to raise_error
end
end

Expand Down
10 changes: 4 additions & 6 deletions spec/lib/phlexy_ui/tabs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,7 @@
context "when condition doesn't exist" do
it "raises an error" do
expect { render described_class.new(:foo) }
.to raise_error(
ArgumentError,
"Modifier `foo` is not defined for PhlexyUI::Tabs"
)
.not_to raise_error
end
end

Expand Down Expand Up @@ -216,13 +213,13 @@
Class.new(Phlex::HTML) do
def view_template(&)
render PhlexyUI::Tabs.new :lifted, id: "my_tabs_2" do |tabs|
tabs.tab "Tab 1", :active, data: {my: :tabs} do |tab|
tabs.tab "Tab 1", :active, :closed, data: {my: :tabs} do |tab|
tab.content class: "bg-base-100 border-base-300 rounded-box p-6" do
"Tab content 1"
end
end

tabs.tab "Tab 2", :checked, class: "text-primary" do |tab|
tabs.tab "Tab 2", :open, class: "text-primary" do |tab|
tab.content class: "bg-base-100 border-base-300 rounded-box p-6", data: {my: :contents} do
"Tab content 2"
end
Expand All @@ -245,6 +242,7 @@ def view_template(&)
class="tab tab-active"
role="tab"
aria-label="Tab 1"
closed
data-my="tabs">
<div role="tabpanel"
class="tab-content
Expand Down

0 comments on commit b6e322e

Please sign in to comment.