defmodule RiverConnectWeb.Components.UI.Slider do @moduledoc """ Implementation of slider component for selecting values within a range. Sliders provide users with a visual representation of a value within a range, and allow them to adjust it by dragging a thumb or pressing arrow keys. ## Examples: <.slider id="volume-slider" min={0} max={100} value={50} on-value-changed={JS.push("volume_changed")} /> <.slider id="price-range" min={10} max={1000} step={10} value={500} class="w-[300px]" /> """ use RiverConnectWeb.Components.UI, :component @doc """ Renders a slider component. ## Options * `:id` - Required unique identifier for the slider. * `:min` - Minimum value (defaults to 0). * `:max` - Maximum value (defaults to 100). * `:step` - Step size for value changes (defaults to 1). * `:value` - Current value of the slider (defaults to min). * `:default-value` - Default value if value is not provided. * `:disabled` - Whether the slider is disabled (defaults to false). * `:on-value-changed` - Handler for value changed event. * `:class` - Additional CSS classes. """ attr :id, :string, required: true, doc: "Unique identifier for the slider" attr :name, :any, default: nil, doc: "Name of the slider for form submission" attr :min, :integer, default: 0, doc: "Minimum value" attr :max, :integer, default: 100, doc: "Maximum value" attr :step, :integer, default: 1, doc: "Step size for value changes" attr :value, :integer, default: nil, doc: "Current value of the slider" attr :"default-value", :integer, default: nil, doc: "Default value if value is not provided" attr :disabled, :boolean, default: false, doc: "Whether the slider is disabled" attr :"on-value-changed", :any, default: nil, doc: "Handler for value changed event" attr :field, Phoenix.HTML.FormField, doc: "A form field struct retrieved from the form, for example: @form[:volume]" attr :class, :string, default: nil attr :rest, :global def slider(assigns) do assigns = prepare_assign(assigns) # Set value from default-value or min if value is not provided value = cond do not is_nil(assigns.value) -> assigns.value not is_nil(assigns[:"default-value"]) -> assigns[:"default-value"] true -> assigns.min end # Ensure value is within bounds and snapped to step value = value |> max(assigns.min) |> min(assigns.max) |> snap_to_step(assigns.step) # Collect event mappings event_map = add_event_mapping(%{}, assigns, "value-changed", :"on-value-changed") # Create options object options = %{ min: assigns.min, max: assigns.max, step: assigns.step, defaultValue: assigns[:"default-value"], disabled: assigns.disabled } assigns = assigns |> assign(:value, value) |> assign(:event_map, json(event_map)) |> assign(:options, json(options)) ~H"""