defmodule PUI.Input do @moduledoc """ Form input components including text inputs, checkboxes, radio buttons, switches, and textareas. ## Basic Text Input <.input type="text" name="username" placeholder="Enter username" /> ## Input with Label <.input type="email" label="Email" placeholder="you@example.com" /> ## With Phoenix Form <.form for={@form} phx-change="validate"> <.input field={@form[:email]} type="email" label="Email" /> <.input field={@form[:password]} type="password" label="Password" /> ## Input Types Supports various HTML input types: <.input type="text" placeholder="Text input" /> <.input type="email" placeholder="Email input" /> <.input type="password" placeholder="Password" /> <.input type="number" placeholder="Number" /> <.input type="file" /> <.input type="date" /> ## Checkbox <.checkbox id="terms" label="I agree to the terms" /> Or with custom label: ## Radio Button ## Switch/Toggle <.switch id="notifications" label="Enable notifications" /> ## Textarea <.textarea label="Description" placeholder="Enter description..." /> ## Disabled State <.input type="text" disabled placeholder="Disabled input" /> <.checkbox id="terms" disabled label="Disabled checkbox" /> ## Attributes (input/1) | Attribute | Type | Default | Description | |-----------|------|---------|-------------| | `type` | `string` | `"text"` | Input type (text, email, password, etc.) | | `label` | `string` | `nil` | Label text (creates wrapped label + input) | | `field` | `FormField` | `nil` | Phoenix form field struct | | `class` | `string` | `""` | Additional CSS classes | | `id` | `any` | `nil` | Input ID | ## Global Attributes All standard HTML input attributes are supported: `accept`, `autocomplete`, `disabled`, `max`, `min`, `pattern`, `placeholder`, `readonly`, `required`, etc. """ use Phoenix.Component attr :id, :any, default: nil attr :class, :string, default: "" attr :type, :string, default: "text" attr :label, :string, default: nil attr :field, Phoenix.HTML.FormField, default: nil, doc: "a form field struct retrieved from the form, for example: @form[:email]" attr :rest, :global, include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength multiple pattern placeholder readonly required rows size step name value) def input(%{label: label} = assigns) when label not in ["", nil] do assigns = map_field(assigns) ~H"""
<.label for={@id}>{@label} <.input id={@id} class={@class} type={@type} field={@field} {@rest} />
""" end def input(assigns) do assigns = map_field(assigns) ~H""" """ end attr :class, :string, default: "" attr :rest, :global, include: ~w(for) slot :inner_block def label(assigns) do ~H""" """ end attr :id, :any, default: nil attr :label, :string, default: nil attr :class, :string, default: nil attr :field, Phoenix.HTML.FormField, default: nil, doc: "a form field struct retrieved from the form, for example: @form[:email]" attr :rest, :global, include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength multiple pattern placeholder readonly required rows size step checked name value) slot :inner_block def checkbox(%{label: label} = assigns) when label != nil do ~H""" """ end def checkbox(assigns) do assigns = map_field(assigns) ~H""" """ end attr :id, :any, default: nil attr :rest, :global, include: ~w(checked name value) attr :class, :string, default: "" attr :field, Phoenix.HTML.FormField, default: nil, doc: "a form field struct retrieved from the form, for example: @form[:email]" def radio(assigns) do assigns = map_field(assigns) ~H""" """ end attr :id, :any, default: nil attr :class, :string, default: "" attr :label, :string, default: nil attr :field, Phoenix.HTML.FormField, default: nil, doc: "a form field struct retrieved from the form, for example: @form[:email]" attr :rest, :global, include: ~w(accept capture cols disabled form list max maxlength min minlength multiple pattern placeholder readonly required rows size step name value) def switch(%{label: label} = assigns) when label != nil do assigns = map_field(assigns) ~H""" """ end def switch(assigns) do assigns = map_field(assigns) ~H""" """ end @doc """ """ attr :id, :any, default: nil attr :class, :string, default: "" attr :label, :string, default: nil attr :field, Phoenix.HTML.FormField, default: nil, doc: "a form field struct retrieved from the form, for example: @form[:email]" attr :rest, :global, include: ~w(accept capture cols disabled form list max maxlength min minlength multiple pattern placeholder readonly required rows size step name value) def textarea(%{label: label} = assigns) when label not in ["", nil] do assigns = map_field(assigns) ~H"""
<.label for={@id}>{@label} <.textarea id={@id} class={@class} field={@field} {@rest} />
""" end def textarea(assigns) do assigns = map_field(assigns) ~H""" """ end def map_field(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do rest = assigns |> Map.get(:rest, %{}) |> Map.put(:name, field.name) |> then(fn rest -> type = Map.get(rest, :type, "text") rest |> Map.put(:value, Phoenix.HTML.Form.normalize_value(type, field.value)) end) assigns |> assign(:id, assigns.id || field.id) |> assign(:field, nil) |> assign(:rest, rest) end def map_field(assigns) do assigns end def generate_id(prefix \\ "input"), do: "#{prefix}_#{System.unique_integer([:positive])}" end