From a57ffc841e9a33afcd27be6267e2bf11e2ed9e2a Mon Sep 17 00:00:00 2001
From: David Alejandro
<15317732+davidalejandroaguilar@users.noreply.github.com>
Date: Tue, 3 Sep 2024 20:52:05 +0900
Subject: [PATCH] Allow adding custom modifiers
---
lib/phlexy_ui/base.rb | 1 +
lib/phlexy_ui/class_list.rb | 25 ++++++-
lib/phlexy_ui/configurable.rb | 24 +++++++
spec/lib/phlexy_ui/card_spec.rb | 120 ++++++++++++++++++++++++++++++++
4 files changed, 167 insertions(+), 3 deletions(-)
diff --git a/lib/phlexy_ui/base.rb b/lib/phlexy_ui/base.rb
index c0651a2..acf238e 100644
--- a/lib/phlexy_ui/base.rb
+++ b/lib/phlexy_ui/base.rb
@@ -18,6 +18,7 @@ def generate_classes!(
modifiers_map: {}
)
ClassList.new(
+ component: self,
component_html_class:,
base_modifiers:,
options:,
diff --git a/lib/phlexy_ui/class_list.rb b/lib/phlexy_ui/class_list.rb
index 27c6275..4af0b1e 100644
--- a/lib/phlexy_ui/class_list.rb
+++ b/lib/phlexy_ui/class_list.rb
@@ -2,7 +2,13 @@ module PhlexyUI
class ClassList
RESPONSIVE_PREFIXES = %i[sm md lg].freeze
- def initialize(component_html_class: nil, base_modifiers: [], options: {}, modifiers_map: {})
+ def initialize(
+ component:,
+ component_html_class: nil,
+ base_modifiers: [],
+ options: {},
+ modifiers_map: {}
+ )
@component_html_class = component_html_class
@base_modifiers = base_modifiers
@options = options
@@ -22,10 +28,17 @@ def to_a
attr_reader :component_html_class, :base_modifiers, :options, :modifiers_map
- def selected_base_modifiers_classes
+ def selected_base_modifiers
base_modifiers.select { |modifier| modifiers_map.key?(modifier) }
end
+ def selected_custom_modifiers
+ base_modifiers.select do |modifier|
+ PhlexyUI.configuration.modifiers.key?(modifier, component:) ||
+ PhlexyUI.configuration.modifiers.key?(modifier)
+ end
+ end
+
def add_component_class(classes)
return unless component_html_class
@@ -35,7 +48,13 @@ def add_component_class(classes)
def add_selected_modifiers_classes(classes)
classes.concat(
html_classes_for_modifiers(
- selected_base_modifiers_classes
+ selected_base_modifiers
+ )
+ )
+
+ classes.concat(
+ html_classes_for_modifiers(
+ selected_custom_modifiers
)
)
end
diff --git a/lib/phlexy_ui/configurable.rb b/lib/phlexy_ui/configurable.rb
index 150fcee..31e456c 100644
--- a/lib/phlexy_ui/configurable.rb
+++ b/lib/phlexy_ui/configurable.rb
@@ -10,12 +10,36 @@ def configuration
@configuration ||= Configuration.new
end
+ class Modifiers
+ def initialize
+ @modifiers = {}
+ end
+
+ def add(modifier, classes:, component: nil)
+ @modifiers[component] ||= {}
+ @modifiers[component][modifier] = classes
+ end
+
+ def remove(modifier, component: nil)
+ @modifiers[component] ||= {}
+ @modifiers[component]&.delete(modifier)
+ end
+
+ def for(component: nil)
+ @modifiers[component] || {}
+ end
+ end
+
class Configuration
attr_accessor :prefix
def initialize
@prefix = nil
end
+
+ def modifiers
+ @modifiers ||= Modifiers.new
+ end
end
end
end
diff --git a/spec/lib/phlexy_ui/card_spec.rb b/spec/lib/phlexy_ui/card_spec.rb
index 462ca49..8ed4dcf 100644
--- a/spec/lib/phlexy_ui/card_spec.rb
+++ b/spec/lib/phlexy_ui/card_spec.rb
@@ -107,6 +107,81 @@
end
end
+ describe "custom modifiers" do
+ context "when there's a custom modifier for the component" do
+ around do |example|
+ PhlexyUI.configure do |config|
+ config.modifiers.add(
+ :my_modifier,
+ component: PhlexyUI::Card,
+ classes: "w-96 shadow-xl"
+ )
+ end
+
+ example.run
+
+ PhlexyUI.configure do |config|
+ config.modifiers.remove(:my_modifier, component: PhlexyUI::Card)
+ end
+ end
+
+ subject(:output) do
+ render described_class.new(:my_modifier)
+ end
+
+ it "renders it correctly" do
+ expected_html = html <<~HTML
+
+ HTML
+
+ expect(output).to eq(expected_html)
+ end
+ end
+
+ context "when there's a custom modifier without a specific component" do
+ around do |example|
+ PhlexyUI.configure do |config|
+ config.modifiers.add(
+ :my_modifier,
+ classes: "w-96 shadow-xl"
+ )
+ end
+
+ example.run
+
+ PhlexyUI.configure do |config|
+ config.modifiers.remove(:my_modifier)
+ end
+ end
+
+ subject(:output) do
+ render described_class.new(:my_modifier)
+ end
+
+ it "renders it correctly" do
+ expected_html = html <<~HTML
+
+ HTML
+
+ expect(output).to eq(expected_html)
+ end
+ end
+
+ context "when there's no custom modifier" do
+ subject(:output) do
+ render described_class.new(:my_modifier)
+ end
+
+ it "does not render it" do
+ expected_html = html <<~HTML
+
+ HTML
+
+ expect(output).to eq(expected_html)
+ end
+ end
+ end
+
describe "responsiveness" do
%i[sm md lg].each do |viewport|
context "when given an :#{viewport} responsive option as a single argument" do
@@ -181,6 +256,51 @@
expect(output).to eq(expected_html)
end
end
+
+ context "when there are custom modifiers" do
+ around do |example|
+ PhlexyUI.configure do |config|
+ config.modifiers.add(
+ :my_modifier,
+ component: PhlexyUI::Card,
+ classes: "w-96 shadow-xl"
+ )
+
+ config.modifiers.add(
+ :my_other_modifier,
+ classes: "p-4 rounded-box"
+ )
+ end
+
+ example.run
+
+ PhlexyUI.configure do |config|
+ config.modifiers.remove(:my_modifier, component: PhlexyUI::Card)
+ config.modifiers.remove(:my_other_modifier)
+ end
+ end
+
+ subject(:output) do
+ render described_class.new(
+ :my_modifier,
+ viewport => :my_other_modifier
+ )
+ end
+
+ it "renders it separately with a responsive prefix" do
+ expected_html = html <<~HTML
+