use leptos::prelude::*;
use crate::meta::DisabledState;
#[component]
pub fn SliderPrimitive(
children: Children,
#[prop(default = 0.0)] min: f64,
#[prop(default = 100.0)] max: f64,
#[prop(default = 1.0)] step: f64,
#[prop(default = 0.0)] value: f64,
#[prop(into, default = "horizontal".to_string())] orientation: String,
#[prop(default = DisabledState::Enabled)] disabled: DisabledState,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
let uid_sl = crate::infra::uid::generate("sl");
let safe_value = if value.is_nan() { min } else { value };
let safe_min = if min.is_nan() { 0.0 } else { min };
let safe_max = if max.is_nan() || max <= safe_min { safe_min + 100.0 } else { max };
let clamped_value = safe_value.clamp(safe_min, safe_max);
let percent = ((clamped_value - safe_min) / (safe_max - safe_min)) * 100.0;
view! {
<div
data-rs-slider=""
data-rs-uid=uid_sl
data-rs-interaction="gesture"
data-rs-orientation=orientation.clone()
data-rs-disabled=if disabled.disabled() { Some("disabled") } else { None }
data-rs-min=safe_min.to_string()
data-rs-max=safe_max.to_string()
data-rs-value=clamped_value.to_string()
data-rs-percent=percent.to_string()
data-rs-step=step.to_string()
role="slider"
aria-valuemin=min.to_string()
aria-valuemax=max.to_string()
aria-valuenow=clamped_value.to_string()
aria-orientation=orientation
aria-disabled=disabled.aria_disabled()
tabindex=if disabled == DisabledState::Disabled { "-1" } else { "0" }
class=class
>
{children()}
</div>
}
}
#[component]
pub fn SliderTrackPrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<div data-rs-slider-track="" class=class>
{children()}
</div>
}
}
#[component]
pub fn SliderRangePrimitive(
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<div data-rs-slider-range="" class=class />
}
}
#[component]
pub fn SliderThumbPrimitive(
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<div data-rs-slider-thumb="" tabindex="0" aria-label="Slider thumb" class=class />
}
}
#[component]
pub fn SliderMarksPrimitive(
#[prop(default = 0.0)] min: f64,
#[prop(default = 100.0)] max: f64,
#[prop(default = 10.0)] step: f64,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
let safe_step = if step <= 0.0 { 10.0 } else { step };
let count = ((max - min) / safe_step).round() as usize + 1;
let marks: Vec<f64> = (0..count)
.map(|i| min + i as f64 * safe_step)
.filter(|v| *v <= max + 1e-9)
.collect();
view! {
<div data-rs-slider-marks="" class=class>
{marks.into_iter().map(|v| {
let pct = ((v - min) / (max - min)) * 100.0;
let style = format!("left: {:.4}%", pct);
view! { <span data-rs-slider-mark="" style=style /> }
}).collect::<Vec<_>>()}
</div>
}
}