use dioxus::prelude::*;
use crate::types::Color;
#[derive(Clone, PartialEq, Props)]
pub struct ListGroupProps {
#[props(default)]
pub flush: bool,
#[props(default)]
pub numbered: bool,
#[props(default)]
pub tag: String,
#[props(default)]
pub class: String,
#[props(extends = GlobalAttributes)]
attributes: Vec<Attribute>,
pub children: Element,
}
#[component]
pub fn ListGroup(props: ListGroupProps) -> Element {
let mut classes = vec!["list-group".to_string()];
if props.flush {
classes.push("list-group-flush".to_string());
}
if props.numbered {
classes.push("list-group-numbered".to_string());
}
if !props.class.is_empty() {
classes.push(props.class.clone());
}
let full_class = classes.join(" ");
if props.tag == "div" {
rsx! {
div { class: "{full_class}", ..props.attributes, {props.children} }
}
} else if props.numbered {
rsx! {
ol { class: "{full_class}", ..props.attributes, {props.children} }
}
} else {
rsx! {
ul { class: "{full_class}", ..props.attributes, {props.children} }
}
}
}
#[derive(Clone, PartialEq, Props)]
pub struct ListGroupItemProps {
#[props(default)]
pub active: bool,
#[props(default)]
pub disabled: bool,
#[props(default)]
pub color: Option<Color>,
#[props(default)]
pub onclick: Option<EventHandler<MouseEvent>>,
#[props(default)]
pub tag: String,
#[props(default)]
pub class: String,
#[props(extends = GlobalAttributes)]
attributes: Vec<Attribute>,
pub children: Element,
}
fn list_group_item_element(tag: &str, has_onclick: bool) -> &'static str {
if tag == "div" {
"div"
} else if has_onclick {
"button"
} else {
"li"
}
}
#[component]
pub fn ListGroupItem(props: ListGroupItemProps) -> Element {
let mut classes = vec!["list-group-item".to_string()];
if props.active {
classes.push("active".to_string());
}
if props.disabled {
classes.push("disabled".to_string());
}
if let Some(ref c) = props.color {
classes.push(format!("list-group-item-{c}"));
}
if props.onclick.is_some() {
classes.push("list-group-item-action".to_string());
}
if !props.class.is_empty() {
classes.push(props.class.clone());
}
let full_class = classes.join(" ");
match list_group_item_element(&props.tag, props.onclick.is_some()) {
"div" => {
let handler = props.onclick;
rsx! {
div {
class: "{full_class}",
onclick: move |evt| {
if let Some(handler) = &handler {
handler.call(evt);
}
},
..props.attributes,
{props.children}
}
}
}
"button" => {
let handler = props.onclick.expect("button form implies a handler");
rsx! {
button {
class: "{full_class}",
r#type: "button",
disabled: props.disabled,
onclick: move |evt| handler.call(evt),
..props.attributes,
{props.children}
}
}
}
_ => rsx! {
li { class: "{full_class}", ..props.attributes, {props.children} }
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn item_defaults_to_li() {
assert_eq!(list_group_item_element("", false), "li");
}
#[test]
fn a_handler_alone_makes_it_a_button() {
assert_eq!(list_group_item_element("", true), "button");
}
#[test]
fn an_explicit_div_wins_over_the_handler() {
assert_eq!(list_group_item_element("div", true), "div");
assert_eq!(list_group_item_element("div", false), "div");
}
}