pub mod step;
pub mod completed;
pub use step::{StepperStep, StepperStepProps, StepState};
pub use completed::{StepperCompleted, StepperCompletedProps};
use dioxus::prelude::*;
#[derive(Clone, Copy, PartialEq, Debug, Default)]
pub enum StepperOrientation {
#[default]
Horizontal,
Vertical,
}
impl StepperOrientation {
pub const ALL: &'static [StepperOrientation] = &[
StepperOrientation::Horizontal,
StepperOrientation::Vertical,
];
#[must_use]
pub fn as_class(&self) -> &'static str {
match self {
StepperOrientation::Horizontal => "sd-stepper--horizontal",
StepperOrientation::Vertical => "sd-stepper--vertical",
}
}
#[must_use]
pub fn name(&self) -> &'static str {
match self {
StepperOrientation::Horizontal => "Horizontal",
StepperOrientation::Vertical => "Vertical",
}
}
}
#[derive(Clone, PartialEq)]
pub struct StepperCtx {
pub active: usize,
pub orientation: StepperOrientation,
pub allow_click_completed: bool,
pub on_change: Option<EventHandler<usize>>,
}
#[derive(Props, Clone, PartialEq)]
pub struct StepperProps {
#[props(default)]
pub active: usize,
#[props(default)]
pub orientation: Option<StepperOrientation>,
#[props(default = true)]
pub allow_click_completed: bool,
#[props(default)]
pub on_change: Option<EventHandler<usize>>,
#[props(default)]
pub class: String,
pub children: Element,
}
#[component]
pub fn Stepper(props: StepperProps) -> Element {
let orientation = props.orientation.unwrap_or_default();
let mut ctx = use_context_provider(|| Signal::new(StepperCtx {
active: props.active,
orientation,
allow_click_completed: props.allow_click_completed,
on_change: props.on_change,
}));
let current = StepperCtx {
active: props.active,
orientation,
allow_click_completed: props.allow_click_completed,
on_change: props.on_change,
};
if *ctx.peek() != current {
*ctx.write() = current;
}
#[cfg(feature = "theme")]
let theme_val = crate::theme::use_theme()();
#[cfg(feature = "theme")]
let base_override = theme_val.resolve_component_base("stepper").unwrap_or("");
#[cfg(feature = "theme")]
let class_modifiers = theme_val.resolve_class_modifiers("stepper", &props.class);
#[cfg(not(feature = "theme"))]
let base_override = "";
#[cfg(not(feature = "theme"))]
let class_modifiers = String::new();
let orientation_class = orientation.as_class();
rsx! {
div {
class: "sd-stepper {orientation_class} {base_override} {class_modifiers} {props.class}",
{props.children}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stepper_orientation_classes() {
assert_eq!(StepperOrientation::Horizontal.as_class(), "sd-stepper--horizontal");
assert_eq!(StepperOrientation::Vertical.as_class(), "sd-stepper--vertical");
}
#[test]
fn test_step_state_classes() {
assert_eq!(StepState::Upcoming.as_class(), "sd-stepper-step--upcoming");
assert_eq!(StepState::Active.as_class(), "sd-stepper-step--active");
assert_eq!(StepState::Completed.as_class(), "sd-stepper-step--completed");
assert_eq!(StepState::Error.as_class(), "sd-stepper-step--error");
}
}