use leptos::prelude::*;
use orbital_base_components::{RatingColor, RatingSize};
use orbital_macros::component_doc;
use orbital_style::inject_style;
use super::injection::RatingInjection;
use super::rating_item::RatingItem;
use super::styles::rating_styles;
#[component_doc(
category = "Data Display",
preview_slug = "rating-display",
preview_label = "Rating Display",
preview_icon = icondata::AiStarOutlined,
)]
#[component]
pub fn RatingDisplay(
#[prop(optional, into)]
class: MaybeProp<String>,
#[prop(optional, into)]
value: Signal<f32>,
#[prop(default = 5.into(), into)]
max: Signal<u8>,
#[prop(default = RatingSize::Medium.into(), into)]
size: Signal<RatingSize>,
#[prop(optional, into)]
color: Signal<RatingColor>,
) -> impl IntoView {
inject_style("orbital-rating", rating_styles());
let bound_value = RwSignal::new(Some(value.get_untracked()));
Effect::new(move |_| {
bound_value.set(Some(value.get()));
});
let class = MaybeProp::derive(move || {
let mut parts = vec![
"orbital-rating-display".to_string(),
format!("orbital-rating-display--{}", size.get().as_str()),
];
if let Some(extra) = class.get() {
if !extra.is_empty() {
parts.push(extra);
}
}
Some(parts.join(" "))
});
view! {
<div role="img" class=class>
<leptos::context::Provider value=RatingInjection {
value: bound_value.into(),
hovered_value: RwSignal::new(None::<f32>),
name: Signal::from(String::new()),
step: 0.5.into(),
size,
color,
interactive: false,
}>
{move || {
let mut max = max.get();
if max < 2 {
max = 2;
}
(0..max)
.map(|i| view! { <RatingItem value=i + 1 /> })
.collect_view()
}}
</leptos::context::Provider>
<span aria-hidden="true" class="orbital-rating-display__value-text">
{move || value.get()}
</span>
</div>
}
}