react/event/handlers.rs
1//! # Design principles
2//!
3//! props builder methods should accept all of the following types:
4//!
5//! ```
6//! # use std::rc::Rc;
7//! # use react::{IntoPropValue, event::{ IntoJsEventHandler, MouseEvent }};
8//! # struct MyPropsBuilder;
9//! # impl MyPropsBuilder {
10//! # fn on_click<F: ?Sized + react::DynFn>(&self, _handler: Option<react::AnyFn<F>>)
11//! # where
12//! # react::AnyFn<F>: IntoJsEventHandler<MouseEvent> {}
13//! # }
14//! # let builder = MyPropsBuilder;
15//! # builder.on_click(IntoPropValue::into_prop_value(
16//! || {}
17//! # ));
18//! # builder.on_click(IntoPropValue::into_prop_value(
19//! |_event| {}
20//! # ));
21//! # builder.on_click(IntoPropValue::into_prop_value(
22//! Rc::new(|| {})
23//! # ));
24//! # builder.on_click(IntoPropValue::into_prop_value(
25//! Rc::new(|_event| {})
26//! # ));
27//! # builder.on_click(IntoPropValue::into_prop_value(
28//! &Rc::new(|| {})
29//! # ));
30//! # builder.on_click(IntoPropValue::into_prop_value(
31//! &Rc::new(|_event| {})
32//! # ));
33//!
34//! # builder.on_click(IntoPropValue::into_prop_value(
35//! Some(|| {})
36//! # ));
37//! # builder.on_click(IntoPropValue::into_prop_value(
38//! Some(Rc::new(|| {}))
39//! # ));
40//! # builder.on_click(IntoPropValue::into_prop_value(
41//! Some(Rc::new(|_event| {}))
42//! # ));
43//! # builder.on_click(IntoPropValue::into_prop_value(
44//! Some(&Rc::new(|| {}))
45//! # ));
46//! # builder.on_click(IntoPropValue::into_prop_value(
47//! Some(&Rc::new(|_event| {}))
48//! # ));
49//! ```
50use convert_js::FromJs;
51use wasm_bindgen::UnwrapThrowExt;
52
53use crate::SafeIntoJsRuntime;
54
55pub trait IntoJsEventHandler<TEvent> {
56 fn into_js_event_handler(self) -> crate::PassedToJsRuntime;
57}
58
59/// `Fn()` can be handlers for any event
60impl<TEvent> IntoJsEventHandler<TEvent> for crate::AnyFn<dyn Fn()> {
61 #[inline]
62 fn into_js_event_handler(self) -> crate::PassedToJsRuntime {
63 self.safe_into_js_runtime()
64 }
65}
66
67/// `Fn(TEvent)` can be handlers for `TEvent`
68impl<TEvent: 'static + FromJs> IntoJsEventHandler<TEvent> for crate::AnyFn<dyn Fn(TEvent)>
69where
70 TEvent::Error: std::fmt::Debug,
71{
72 #[inline]
73 fn into_js_event_handler(self) -> crate::PassedToJsRuntime {
74 crate::AnyFn::new(move |js_value: wasm_bindgen::JsValue| {
75 let event = TEvent::from_js(js_value).unwrap_throw();
76 (self.0.as_ref())(event);
77 })
78 .safe_into_js_runtime()
79 }
80}