1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
#[macro_export]
macro_rules! def_element {
(
$(
$(#[$attr:meta])*
$name:ident {
$(
$(#[$attr_method:meta])*
$fil:ident,
)*
};
)*
) => {
$(
$crate::impl_element!(
$(#[$attr])*
$name {
$(
$(#[$attr_method])*
$fil,
)*
};
);
)*
/// This module contains helpers for rust analyzer autocompletion
#[doc(hidden)]
pub mod completions {
/// This helper tells rust analyzer that it should autocomplete the element name with braces.
#[allow(non_camel_case_types)]
pub enum CompleteWithBraces {
$(
$(#[$attr])*
$name {}
),*
}
}
};
}
#[macro_export]
macro_rules! impl_element {
(
$(
$(#[$attr:meta])*
$name:ident {
$(
$(#[$attr_method:meta])*
$fil:ident,
)*
};
)*
) => {
$(
#[allow(non_camel_case_types)]
$(#[$attr])*
pub mod $name {
#[doc(hidden)]
pub const TAG_NAME: &'static str = stringify!($name);
#[doc(hidden)]
pub const NAME_SPACE: Option<&'static str> = None;
$(
pub use $crate::attributes::$fil::$fil;
)*
}
)*
};
}
#[macro_export]
macro_rules! def_attribute {
(
$(
$(#[$attr:meta])*
$fil:ident,
)*
) => {
$(
#[allow(non_camel_case_types)]
pub mod $fil {
#[allow(non_upper_case_globals)]
$(#[$attr])*
pub const $fil: (&'static str, Option<&'static str>, bool) = (stringify!($fil), None, false);
}
)*
};
}
#[macro_export]
macro_rules! impl_event {
(
$data:ty;
$(
$( #[$attr:meta] )*
$name:ident $(: $event:literal)?
)*
) => {
$(
$( #[$attr] )*
#[inline]
pub fn $name<__Marker>(mut _f: impl ::dioxus_core::prelude::SuperInto<::dioxus_core::prelude::EventHandler<::dioxus_core::Event<$data>>, __Marker>) -> ::dioxus_core::Attribute {
// super into will make a closure that is owned by the current owner (either the child component or the parent component).
// We can't change that behavior in a minor version because it would cause issues with Components that accept event handlers.
// Instead we run super into with an owner that is moved into the listener closure so it will be dropped when the closure is dropped.
let owner = <::generational_box::UnsyncStorage as ::generational_box::AnyStorage>::owner();
let event_handler = ::dioxus_core::prelude::with_owner(owner.clone(), || _f.super_into());
::dioxus_core::Attribute::new(
impl_event!(@name $name $($event)?),
::dioxus_core::AttributeValue::listener(move |e: ::dioxus_core::Event<$crate::events::ErasedEventData>| {
// Force the owner to be moved into the event handler
_ = &owner;
event_handler.call(e.map(|e| e.into()));
}),
None,
false,
).into()
}
#[doc(hidden)]
$( #[$attr] )*
pub mod $name {
use super::*;
// When expanding the macro, we use this version of the function if we see an inline closure to give better type inference
$( #[$attr] )*
pub fn call_with_explicit_closure<
__Marker,
Return: ::dioxus_core::SpawnIfAsync<__Marker> + 'static,
>(
event_handler: impl FnMut(::dioxus_core::Event<$data>) -> Return + 'static,
) -> ::dioxus_core::Attribute {
#[allow(deprecated)]
super::$name(event_handler)
}
}
)*
};
(@name $name:ident) => {
stringify!($name)
};
}
#[doc(hidden)]
#[allow(dead_code)]
pub trait EventReturn<P>: Sized {
fn spawn(self) {}
}
impl EventReturn<()> for () {}
#[doc(hidden)]
pub struct AsyncMarker;
impl<T> EventReturn<AsyncMarker> for T
where
T: std::future::Future<Output = ()> + 'static,
{
#[inline]
fn spawn(self) {
dioxus_core::prelude::spawn(self);
}
}