defmodule PhoenixDuskmoon.Component.DataEntry.Select do @moduledoc """ Select dropdown component for single selection. ## Examples <.dm_form for={@form} phx-submit="save"> <.dm_select field={@form[:country]} label="Country" options={country_options()} /> <.dm_select field={@form[:priority]} label="Priority" options={priority_options()} color="warning" /> <.dm_select field={@form[:category]} label="Category"> """ use Phoenix.Component import PhoenixDuskmoon.Component.DataEntry.Form, only: [dm_error: 1] import PhoenixDuskmoon.Component.Helpers, only: [css_color: 1] @doc """ Renders a select dropdown. ## Examples <.dm_select field={@form[:country]} label="Country" options={[{"us", "USA"}, {"uk", "UK"}]} /> """ @doc type: :component attr(:id, :any, default: nil, doc: "HTML id attribute") attr(:name, :any, doc: "HTML name attribute for form submission") attr(:value, :any, default: nil, doc: "the currently selected value") attr(:field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form") attr(:label, :string, default: nil, doc: "text label displayed above the select") attr(:options, :list, default: nil, doc: "list of {value, label} tuples for options") attr(:prompt, :string, default: nil, doc: "placeholder option text shown when no value selected" ) attr(:size, :string, default: "md", values: ["xs", "sm", "md", "lg"], doc: "select size") attr(:variant, :string, default: "bordered", values: ["ghost", "filled", "bordered", nil], doc: "the select style variant (ghost, filled, bordered)" ) attr(:color, :string, default: "primary", values: ["primary", "secondary", "tertiary", "accent", "info", "success", "warning", "error"], doc: "color variant" ) attr(:helper, :string, default: nil, doc: "helper text displayed below the select") attr(:errors, :list, default: [], doc: "list of error messages to display") attr(:disabled, :boolean, default: false, doc: "disables the select") attr(:horizontal, :boolean, default: false, doc: "horizontal layout (label beside input)") attr(:state, :string, default: nil, values: [nil, "success", "warning"], doc: "validation state (applies form-group-success/warning)" ) attr(:multiple, :boolean, default: false, doc: "allow multiple selections") attr(:class, :any, default: nil, doc: "additional CSS classes for the wrapper") attr(:label_class, :any, default: nil, doc: "additional CSS classes for the label") attr(:select_class, :any, default: nil, doc: "additional CSS classes for the select element") attr(:rest, :global) slot(:inner_block, required: false) def dm_select(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do assigns |> assign(field: nil, id: assigns.id || field.id) |> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end) |> assign(:value, field.value) |> dm_select() end def dm_select(assigns) do assigns = assign(assigns, :color, css_color(assigns.color)) ~H"""
{@helper}
<.dm_error :for={msg <- @errors}>{msg}
""" end defp render_options(%{options: options} = assigns) when is_list(options) do ~H""" """ end defp render_options(assigns) do ~H""" {render_slot(@inner_block)} """ end end