material_dioxus/
checkbox.rs

1use std::marker::PhantomData;
2
3use dioxus::prelude::*;
4use gloo::events::EventListener;
5use wasm_bindgen::prelude::*;
6use web_sys::Node;
7
8use crate::utils::StaticCallback;
9
10#[wasm_bindgen(module = "/build/mwc-checkbox.js")]
11extern "C" {
12    #[derive(Debug)]
13    #[wasm_bindgen(extends = Node)]
14    type Checkbox;
15
16    #[wasm_bindgen(getter, static_method_of = Checkbox)]
17    fn _dummy_loader() -> JsValue;
18
19    #[wasm_bindgen(method, setter)]
20    fn set_checked(this: &Checkbox, value: bool);
21
22    #[wasm_bindgen(method, getter)]
23    fn checked(this: &Checkbox) -> bool;
24}
25
26loader_hack!(Checkbox);
27
28/// Props for [`MatCheckbox`]
29///
30/// MWC Documentation:
31///
32/// - [Properties](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/checkbox#propertiesattributes)
33/// - [Events](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/checkbox#events)
34#[derive(Props)]
35pub struct CheckboxProps<'a> {
36    #[props(default)]
37    pub checked: bool,
38    #[props(default)]
39    pub indeterminate: bool,
40    #[props(default)]
41    pub disabled: bool,
42    #[props(into)]
43    pub value: Option<String>,
44    #[props(default)]
45    pub reduced_touch_target: bool,
46    /// Binds to `change` event on `mwc-checkbox`
47    ///
48    /// See events docs to learn more.
49    #[props(into)]
50    // the name cannot start with `on` or dioxus will expect an `EventHandler` which aren't static
51    // and thus cannot be used here
52    pub _onchange: Option<StaticCallback<bool>>,
53    _lifetime: Option<PhantomData<&'a ()>>,
54
55    #[props(into, default)]
56    pub style: String,
57    #[props(into, default)]
58    pub class: String,
59    #[props(into)]
60    pub slot: Option<String>,
61    #[props(default)]
62    pub dialog_initial_focus: bool,
63}
64
65fn render<'a>(cx: Scope<'a, CheckboxProps<'a>>) -> Element<'a> {
66    let id = crate::use_id(cx, "checkbox");
67    let change_listener = cx.use_hook(|| None);
68    if let Some(elem) = crate::get_elem_by_id(id) {
69        let target = elem.clone();
70        let cb = JsValue::from(elem).dyn_into::<Checkbox>().unwrap();
71        cb.set_checked(cx.props.checked);
72        if let Some(listener) = cx.props._onchange.clone() {
73            *change_listener = Some(EventListener::new(&target, "change", move |_| {
74                listener.call(cb.checked())
75            }));
76        }
77    }
78    render! {
79        mwc-checkbox {
80            id: id,
81
82            indeterminate: bool_attr!(cx.props.indeterminate),
83            disabled: cx.props.disabled,
84            value: optional_string_attr!(cx.props.value),
85            reducedTouchTarget: bool_attr!(cx.props.reduced_touch_target),
86
87            style: string_attr!(cx.props.style),
88            class: string_attr!(cx.props.class),
89            slot: optional_string_attr!(cx.props.slot),
90            dialogInitialFocus: bool_attr!(cx.props.dialog_initial_focus),
91        }
92    }
93}
94
95component!('a, MatCheckbox, CheckboxProps, render, Checkbox, "checkbox");