use crate::components::icon::*;
use dioxus::prelude::*;
#[derive(Clone, PartialEq, Props)]
pub struct CheckboxProps {
#[props(extends = button, extends = GlobalAttributes)]
attributes: Vec<Attribute>,
#[props(optional, into, default = String::new())]
name: String,
#[props(optional, into, default = String::from("on"))]
value: String,
#[props(optional)]
default_checked: bool,
#[props(optional)]
checked: Signal<bool>,
#[props(optional)]
onchange: Callback<bool, bool>,
}
#[component]
pub fn Checkbox(mut props: CheckboxProps) -> Element {
let default_classes = "checkbox";
crate::setup_class_attribute(&mut props.attributes, default_classes);
let mut checked = use_signal(|| props.default_checked);
let mut prev_default = use_signal(|| props.default_checked);
if *prev_default.peek() != props.default_checked {
*prev_default.write() = props.default_checked;
*checked.write() = props.default_checked;
}
let id = crate::use_unique_id();
rsx! {
button {
type: "button",
role: "checkbox",
"data-checked": if *checked.read() { "checked" } else { "unchecked" },
onclick: move |event| {
let new_checked = !checked();
checked.set(new_checked);
props.checked.set(new_checked);
if props.onchange.call(new_checked) {
event.stop_propagation();
}
},
onkeydown: move |e| {
if e.key() == Key::Enter {
e.prevent_default();
}
},
..props.attributes,
span { class: "checkbox-indicator",
if *checked.read() {
Icon {
icon: Icons::Check
}
}
}
}
input {
id,
type: "checkbox",
name: props.name,
value: props.value,
checked: *checked.read(),
aria_hidden: "true",
tabindex: "-1",
position: "absolute",
pointer_events: "none",
opacity: "0",
margin: "0",
transform: "translateX(-100%)",
}
}
}