Current section

Files

Jump to
moon lib moon components text_input.ex
Raw

lib/moon/components/text_input.ex

defmodule Moon.Components.TextInput do
@moduledoc false
use Moon.StatelessComponent
alias Moon.Components.InputGroup
alias Moon.Components.TextInput.TextInputBasic
alias Moon.Components.TextInput.TextInputInnerLabel
alias Moon.Components.TextInput.TextInputPassword
alias Moon.Components.TextInput.HintText
alias Surface.Components.Context
prop(id, :string)
prop(field, :atom, from_context: {Surface.Components.Form.Field, :field})
prop(size, :string, values: ["md", "lg", "xl"], default: "md")
prop(type, :string,
values: [
"date",
"month",
"datetime-local",
"email",
"number",
"password",
"search",
"tel",
"text",
"time",
"url"
],
default: "text"
)
prop(placeholder, :string, default: " ")
prop(is_error, :boolean)
prop(background_color, :string, values: Moon.colors(), default: "bg-goku")
prop(is_first, :boolean)
prop(disabled, :boolean)
prop(label, :string)
prop(required, :boolean)
prop(step, :string, default: "1")
prop(class, :css_class)
prop(min, :string)
prop(max, :string)
prop(readonly, :boolean)
prop(value, :string)
prop(focus, :event)
prop(keydown, :event)
prop(keyup, :event)
prop(blur, :event)
prop(show_password_text, :string, default: "Show")
prop(use_error_tag, :boolean)
slot(left_icon_slot)
slot(right_icon_slot)
slot(hint_text_slot)
data(form, :form, from_context: {Surface.Components.Form, :form})
data(is_in_input_group, :boolean, from_context: {InputGroup, :is_in_input_group})
data(group_class_plain, :css_class, from_context: {InputGroup, :group_class_plain})
data(internal_render, :any)
def render(assigns) do
assigns = put_everything_to_context(assigns)
internal_render = ~F"""
<HintText :if={slot_assigned?(:hint_text_slot)} {=@is_error}>
<#slot {@hint_text_slot} />
</HintText>
"""
assigns = assign(assigns, internal_render: internal_render)
~F"""
{#if @type == "password"}
<TextInputPassword
{=@id}
{=@field}
class={@class, "#{get_combined_class(@is_in_input_group, @field, @group_class_plain)}": true}
>
<:left_icon_slot>
<#slot {@left_icon_slot} />
</:left_icon_slot>
<:right_icon_slot>
<#slot {@right_icon_slot} />
</:right_icon_slot>
{@internal_render}
</TextInputPassword>
{#elseif @size == "xl"}
<TextInputInnerLabel
{=@id}
{=@field}
class={@class, "#{get_combined_class(@is_in_input_group, @field, @group_class_plain)}": true}
>
<:left_icon_slot>
<#slot {@left_icon_slot} />
</:left_icon_slot>
<:right_icon_slot>
<#slot {@right_icon_slot} />
</:right_icon_slot>
{@internal_render}
</TextInputInnerLabel>
{#else}
<TextInputBasic {=@id} {=@field} {=@class}>
<:left_icon_slot>
<#slot {@left_icon_slot} />
</:left_icon_slot>
<:right_icon_slot>
<#slot {@right_icon_slot} />
</:right_icon_slot>
{@internal_render}
</TextInputBasic>
{/if}
"""
end
defp put_everything_to_context(assigns) do
assigns
|> Context.put(
__MODULE__,
assigns
|> Map.delete(:left_icon_slot)
|> Map.delete(:right_icon_slot)
|> Map.delete(:hint_text_slot)
)
|> Context.put(__MODULE__,
is_error: has_error(assigns[:is_error], assigns[:form], assigns[:field]),
has_left_icon: slot_assigned?(:left_icon_slot),
has_right_icon: slot_assigned?(:right_icon_slot)
)
end
defp get_combined_class(is_in_input_group, field, group_class_plain) do
if is_in_input_group && !field do
group_class_plain
end
end
defp has_error(is_error, form, field) do
is_error || (field && form && Keyword.has_key?(form.errors, field))
end
end