I'm implementing material 3 from scratch with web_sys and writing some adapters for different frameworks among them yew.
I have implemented a basic structure for buttons something like this to use like this.
This works fine on web_sys but I'm trying to write the yew adapter and I'm having problems by casting between yew::Callback<web_sys::MouseEvent>
to FnMut(web_sys::MouseEvent)
.
My adapter looks like this...
this is the definition for button in my core module
And this is the definition in my adapter crate:
In adapter props takes both InnerData and ComponentOpts in one structure
// the properties in yew adapter
#[derive(PartialEq, Properties)]
pub struct ElevatedButtonProps {
pub label: AttrValue,
#[prop_or(false)]
pub disable: bool,
#[prop_or_default]
pub icon: Option<AttrValue>,
#[prop_or_default]
pub onclick: Option<Callback<MouseEvent>>,
}
And the functional component in yew, which is the adapter per se, takes the properties passed to it and with them creates the button with my "core" library and returns it as a virtual node of yew.
/// this is my core library https://gitlab.com/material-rs/material_you_rs/-/tree/agnostic-api/crates/core?ref_type=heads
use core::components::buttons::elevated::{self, ElevatedButtonData, ElevatedButtonOpts};
use web_sys::{HtmlElement, MouseEvent};
use yew::{function_component, virtual_dom::VNode, AttrValue, Callback, Html, Properties};
#[function_component(ElevatedButton)]
pub fn elevated_button(props: &ElevatedButtonProps) -> Html {
let ElevatedButtonProps {
label,
disable,
icon,
onclick,
} = props;
let icon = if let Some(icon) = icon {
Some(icon.to_string())
} else {
None
};
let inner = if let Some(onclick) = onclick {
// problem is here when i'm trying to cast
let cb = move |e: MouseEvent| {
onclick.clone().emit(e.clone());
};
ElevatedButtonData {
label: label.to_string(),
icon,
onclick: Some(Box::new(cb.clone())),
}
} else {
ElevatedButtonData {
label: label.to_string(),
icon,
onclick: None,
}
};
let opts = ElevatedButtonOpts { disable: *disable };
let button: HtmlElement = elevated::ElevatedButton::new(inner, opts);
VNode::VRef(button.into())
}
But this is not working...
The compiler tells me that the yew::Callback
must outlive 'static
, but at the same time the macro annotation function_component
does not allow me lifetimes annotations.
20 | pub fn elevated_button(props: &ElevatedButtonProps) -> Html {
| - let's call the lifetime of this reference `'1`
...
42 | onclick: Some(Box::new(cb.clone())),
| ^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`
does anyone have any idea how I can deal with this?
edit:
"core" is my library where I'm implementing the components only over web_sys and in the adapter I'm "instantiating" it in a comfortable way depending on the framework of the shift