defmodule <%= @module_name %>.UI.Input do
@moduledoc """
A simple input component.
"""
use Phoenix.Component
use CVA.Component
import <%= @module_name %>.UI.Helper
attr(:id, :any, default: nil)
attr(:name, :any)
attr(:label, :string, default: nil)
attr(:value, :any)
attr(:type, :string,
default: "text",
values: ~w(checkbox color date datetime-local email file hidden month number password
range radio search select tel text textarea time url week url-slug)
)
attr(:field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form, for example: @form[:email]")
attr(:errors, :list, default: [])
attr(:checked, :boolean, doc: "the checked flag for checkbox inputs")
attr(:prompt, :string, default: nil, doc: "the prompt for select inputs")
attr(:options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2")
attr(:multiple, :boolean, default: false, doc: "the multiple flag for select inputs")
attr(:class, :any, default: nil)
attr(:rest, :global, include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength
multiple pattern placeholder readonly required rows size step))
slot(:inner_block)
def root(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
assigns
|> assign(field: nil, id: assigns.id || field.id)
|> assign(:errors, Enum.map(field.errors, &translate_error(&1)))
|> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
|> assign_new(:value, fn -> field.value end)
|> root()
end
def root(%{type: "checkbox"} = assigns) do
assigns =
assign_new(assigns, :checked, fn ->
Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
end)
~H"""
<<%= @module_name %>.UI.Label.root for={@id} class={cn(["flex gap-x-2", @class])}>
<%= render_slot(@inner_block) %>
<%= @module_name %>.UI.Label.root>
<<%= @module_name %>.UI.Error.root :for={msg <- @errors}><%= msg %><%= @module_name %>.UI.Error.root>
"""
end
def root(%{type: "select"} = assigns) do
~H"""
<<%= @module_name %>.UI.Label.root for={@id}><%= @label %><%= @module_name %>.UI.Label.root>
<%= @prompt %>
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
<<%= @module_name %>.UI.Error.root :for={msg <- @errors}><%= msg %><%= @module_name %>.UI.Error.root>
"""
end
def root(%{type: "textarea"} = assigns) do
~H"""
<<%= @module_name %>.UI.Label.root for={@id}><%= @label %><%= @module_name %>.UI.Label.root>
<<%= @module_name %>.UI.Error.root :for={msg <- @errors}><%= msg %><%= @module_name %>.UI.Error.root>
"""
end
def root(%{type: "url-slug"} = assigns) do
~H"""
<<%= @module_name %>.UI.Label.root for={@id}><%= @label %><%= @module_name %>.UI.Label.root>
<<%= @module_name %>.UI.Error.root :for={msg <- @errors}><%= msg %><%= @module_name %>.UI.Error.root>
"""
end
# All other inputs text, datetime-local, url, password, etc. are handled here...
def root(assigns) do
~H"""
<<%= @module_name %>.UI.Label.root for={@id}><%= @label %><%= @module_name %>.UI.Label.root>
<<%= @module_name %>.UI.Error.root :for={msg <- @errors}><%= msg %><%= @module_name %>.UI.Error.root>
"""
end
def translate_errors(errors, field) when is_list(errors) do
for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts})
end
def translate_error({msg, opts}) do
if count = opts[:count] do
Gettext.dngettext(UI.Gettext, "errors", msg, msg, count, opts)
else
Gettext.dgettext(UI.Gettext, "errors", msg, opts)
end
end
end