defmodule LiveViewUI.UI.Input do @moduledoc """ A simple input component for various form fields. ## Example Usage Here is a basic example of setting up a text input component: ```elixir ``` You can customize the input with different types, labels, and other attributes: ### Text Input ```elixir ``` ### Email Input ```elixir ``` ### Password Input ```elixir ``` ### Number Input ```elixir ``` ### Checkbox Input ```elixir I agree to the terms and conditions ``` ### Select Input ```elixir ``` ### Textarea Input ```elixir ``` ### Radio Input ```elixir ``` ### Date Input ```elixir ``` ### Time Input ```elixir ``` ### URL Input ```elixir ``` ## Attributes - `:id` - The ID of the input element. Defaults to the field ID if not provided. - `:name` - The name of the input element. - `:label` - The label text for the input element. - `:value` - The value of the input element. - `:type` - The type of the input element. Default is `"text"`. Available options include: - `"checkbox"`, `"color"`, `"date"`, `"datetime-local"`, `"email"`, `"file"`, `"hidden"`, `"month"`, `"number"`, `"password"`, `"radio"`, `"range"`, `"search"`, `"select"`, `"tel"`, `"text"`, `"textarea"`, `"time"`, `"url"`, `"week"` - `:field` - A form field struct retrieved from the form (e.g., `@form[:email]`). - `:errors` - A list of errors for the input element. - `:checked` - The checked flag for checkbox inputs. - `:prompt` - The prompt for select inputs. - `:options` - The options to pass to `Phoenix.HTML.Form.options_for_select/2` for select inputs. - `:multiple` - The multiple flag for select inputs. Default is `false`. - `:class` - Additional CSS classes to apply to the input element. - `:rest` - Any additional attributes to apply to the input element, including `accept`, `autocomplete`, `capture`, `cols`, `disabled`, `form`, `list`, `max`, `maxlength`, `min`, `minlength`, `multiple`, `pattern`, `placeholder`, `readonly`, `required`, `rows`, `size`, `step`. ## Slots - `:inner_block` - The content to be displayed inside the input element (e.g., label for checkbox). ## Components - `Input.root` - The main container for the input component. """ use Phoenix.Component use CVA.Component import LiveViewUI.UI.Helper alias LiveViewUI.UI.Error alias LiveViewUI.UI.Label 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) ) 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"""
<%= render_slot(@inner_block) %>
<%= msg %>
""" end def root(%{type: "select"} = assigns) do ~H"""
<%= @label %> <%= msg %>
""" end def root(%{type: "textarea"} = assigns) do ~H"""
<%= @label %> <%= msg %>
""" end # All other inputs text, datetime-local, url, password, etc. are handled here... def root(assigns) do ~H"""
<%= @label %> <%= msg %>
""" 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