defmodule RiverConnectWeb.Components.UI.Select do @moduledoc """ Implement of select components from https://ui.shadcn.com/docs/components/select ## Examples:
<.select default="banana" id="fruit-select"> <.select_trigger class="w-[180px]"> <.select_value placeholder=".select a fruit"/> <.select_content> <.select_group> <.select_label>Fruits <.select_item value="apple">Apple <.select_item value="banana">Banana <.select_item value="blueberry">Blueberry <.select_separator /> <.select_item disabled value="grapes">Grapes <.select_item value="pineapple">Pineapple <.button type="submit">Submit
""" use RiverConnectWeb.Components.UI, :component @doc """ Ready to use select component with all required parts. """ attr :id, :string, default: nil attr :name, :any, default: nil attr :value, :any, default: nil, doc: "The value of the select" attr :"default-value", :any, default: nil, doc: "The default value of the select" attr :multiple, :boolean, default: false, doc: "Allow multiple selection" attr :"use-portal", :boolean, default: false, doc: "Whether to render the content in a portal" attr :"portal-container", :string, default: nil, doc: "CSS selector for the portal container" attr :"on-value-changed", :any, default: nil, doc: "Handler for value changed event" attr :"on-open", :any, default: nil, doc: "Handler for select open event" attr :"on-close", :any, default: nil, doc: "Handler for select closed event" attr :field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form, for example: @form[:email]" attr :label, :string, default: nil, doc: "The display label of the select value. If not provided, the value will be used." attr :placeholder, :string, default: nil, doc: "The placeholder text when no value is selected." attr :class, :string, default: nil slot :inner_block, required: true attr :rest, :global def select(assigns) do assigns = prepare_assign(assigns) # Collect event mappings event_map = %{} |> add_event_mapping(assigns, "value-changed", :"on-value-changed") |> add_event_mapping(assigns, "opened", :"on-open") |> add_event_mapping(assigns, "closed", :"on-close") assigns = assigns |> assign(:event_map, json(event_map)) |> assign( :options, json(%{ defaultValue: assigns[:"default-value"], value: assigns.value, name: assigns.name, multiple: assigns.multiple, usePortal: assigns[:"use-portal"], portalContainer: assigns[:"portal-container"], animations: get_animation_config() }) ) ~H"""
{render_slot(@inner_block)}
""" end attr :class, :string, default: nil slot :inner_block, required: true attr :rest, :global def select_trigger(assigns) do ~H""" """ end attr :placeholder, :string, default: nil attr :class, :string, default: nil attr :rest, :global def select_value(assigns) do ~H""" """ end attr :class, :string, default: nil attr :side, :string, values: ~w(top bottom), default: "bottom" slot :inner_block, required: true attr :rest, :global def select_content(assigns) do position_class = case assigns.side do "top" -> "bottom-full mb-1" "bottom" -> "top-full mt-1" end assigns = assign(assigns, :position_class, position_class) ~H""" """ end attr :class, :string, default: nil slot :inner_block, required: true attr :rest, :global def select_group(assigns) do ~H"""
{render_slot(@inner_block)}
""" end attr :class, :string, default: nil slot :inner_block, required: true attr :rest, :global def select_label(assigns) do ~H"""
{render_slot(@inner_block)}
""" end attr :value, :string, required: true attr :disabled, :boolean, default: false attr :class, :string, default: nil slot :inner_block, required: true attr :rest, :global def select_item(assigns) do ~H"""
{render_slot(@inner_block)}
""" end def select_separator(assigns) do ~H"""
""" end defp get_animation_config do %{ "open_to_closed" => %{ duration: 130, target_part: "content" } } end end