diff --git a/lib/phlex_ui/attribute_merger.rb b/lib/phlex_ui/attribute_merger.rb index 378fd374f..2e4be008c 100644 --- a/lib/phlex_ui/attribute_merger.rb +++ b/lib/phlex_ui/attribute_merger.rb @@ -1,6 +1,7 @@ module PhlexUI class AttributeMerger attr_reader :default_attrs, :user_attrs + OVERRIDE_KEY = "!".freeze def initialize(default_attrs, user_attrs) @default_attrs = flatten_hash(default_attrs) @@ -12,8 +13,8 @@ def initialize(default_attrs, user_attrs) # ex: if default_attrs = { class: "text-right" }, user_attrs = { class!: "text-left" } # the result will be { class: "text-left } def call - merged_attrs = merge_hashes(default_attrs, user_attrs) - mix(merged_attrs, user_attrs) + merged_attrs = merge_hashes(default_attrs, non_override_attrs) + mix(merged_attrs, override_attrs) end private @@ -28,7 +29,8 @@ def mix(*args) when Array old.is_a?(Array) ? (old + new) : new when String - old.is_a?(String) ? "#{old} #{new}" : new + value = "#{old} #{new}".split.uniq.join(" ") + old.is_a?(String) ? value : new else new end @@ -40,6 +42,18 @@ def mix(*args) end end + def override_attrs + user_attrs.select do |key, value| + key.to_s[-1] == OVERRIDE_KEY + end + end + + def non_override_attrs + user_attrs.reject do |key, value| + key.to_s[-1] == OVERRIDE_KEY + end + end + def flatten_hash(hash, parent_key = "", result_hash = {}) hash.each do |key, value| new_key = parent_key.empty? ? key : :"#{parent_key}_#{key}" diff --git a/lib/rbui/textarea/textarea.rb b/lib/rbui/textarea/textarea.rb new file mode 100644 index 000000000..5869a3bc9 --- /dev/null +++ b/lib/rbui/textarea/textarea.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module RBUI + class Textarea < Base + def initialize(rows: 8, **attrs) + @rows = rows + super(**attrs) + end + + def view_template + textarea(rows: @rows, **attrs) + end + + private + + def default_attrs + { + data: { + rbui__form_field_target: "input", + action: "input->rbui--form-field#onInput invalid->rbui--form-field#onInvalid" + }, + class: "flex w-full rounded-md border bg-background px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 border-border focus-visible:ring-ring placeholder:text-muted-foreground" + } + end + end +end diff --git a/test/phlex_ui/input_test.rb b/test/phlex_ui/input_test.rb index cc64868a8..4c91de62e 100644 --- a/test/phlex_ui/input_test.rb +++ b/test/phlex_ui/input_test.rb @@ -10,7 +10,7 @@ def test_render_with_all_items PhlexUI.Input(type: "email", placeholder: "Email") end - assert_match(/Email/, output) + assert_match(/placeholder="Email"/, output) end def test_no_destructive_classes_when_error_absent diff --git a/test/phlex_ui/select_test.rb b/test/phlex_ui/select_test.rb index 1c31cac38..6f7617df9 100644 --- a/test/phlex_ui/select_test.rb +++ b/test/phlex_ui/select_test.rb @@ -14,7 +14,7 @@ def test_render_with_all_items output = phlex_context do PhlexUI.Select do - PhlexUI.SelectInput + PhlexUI.SelectInput(name: "NAME") PhlexUI.SelectTrigger do PhlexUI.SelectValue(placeholder: "Placeholder") end @@ -29,5 +29,6 @@ def test_render_with_all_items end assert_match(/John/, output) + assert_match('name="NAME"', output) end end