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-radio.js")]
11extern "C" {
12 #[derive(Debug)]
13 #[wasm_bindgen(extends = Node)]
14 type Radio;
15
16 #[wasm_bindgen(getter, static_method_of = Radio)]
17 fn _dummy_loader() -> JsValue;
18
19 #[wasm_bindgen(method, getter)]
20 fn checked(this: &Radio) -> bool;
21
22 #[wasm_bindgen(method, setter)]
23 fn set_checked(this: &Radio, value: bool);
24}
25
26loader_hack!(Radio);
27
28#[derive(Props)]
35pub struct RadioProps<'a> {
36 #[props(default)]
37 pub checked: bool,
38 #[props(default)]
39 pub disabled: bool,
40 #[props(into)]
41 pub name: Option<String>,
42 #[props(into)]
43 pub value: Option<String>,
44 #[props(default)]
45 pub global: bool,
46 #[props(default)]
47 pub reduced_touch_target: bool,
48 #[props(into)]
54 pub _onchange: Option<StaticCallback<bool>>,
57 _lifetime: Option<PhantomData<&'a ()>>,
58
59 #[props(into, default)]
60 pub style: String,
61 #[props(into, default)]
62 pub class: String,
63 #[props(into)]
64 pub slot: Option<String>,
65 #[props(default)]
66 pub dialog_initial_focus: bool,
67}
68
69fn render<'a>(cx: Scope<'a, RadioProps<'a>>) -> Element<'a> {
70 let id = crate::use_id(cx, "radio");
71 let change_listener = cx.use_hook(|| None);
72 if let Some(elem) = crate::get_elem_by_id(id) {
73 let target = elem.clone();
74 let radio = JsValue::from(elem).dyn_into::<Radio>().unwrap();
75 radio.set_checked(cx.props.checked);
76 if let Some(listener) = cx.props._onchange.clone() {
77 *change_listener = Some(EventListener::new(&target, "change", move |_| {
78 listener.call(radio.checked())
79 }));
80 }
81 }
82 render! {
83 mwc-radio {
84 id: id,
85
86 disabled: bool_attr!(cx.props.disabled),
87 name: optional_string_attr!(cx.props.name),
88 value: optional_string_attr!(cx.props.value),
89 global: bool_attr!(cx.props.global),
90 reducedTouchTarget: bool_attr!(cx.props.reduced_touch_target),
91
92 style: string_attr!(cx.props.style),
93 class: string_attr!(cx.props.class),
94 slot: optional_string_attr!(cx.props.slot),
95 dialogInitialFocus: bool_attr!(cx.props.dialog_initial_focus),
96 }
97 }
98}
99
100component!('a, MatRadio, RadioProps, render, Radio, "radio");