use std::any::Any;
use std::sync::RwLock;
macro_rules! impl_event {
(
$data:ty;
$(
$( #[$attr:meta] )*
$name:ident $(: $js_name:literal)?
)*
) => {
$(
$( #[$attr] )*
#[inline]
pub fn $name<E: crate::EventReturn<T>, T>(mut _f: impl FnMut(::dioxus_core::Event<$data>) -> E + 'static) -> ::dioxus_core::Attribute {
::dioxus_core::Attribute::new(
impl_event!(@name $name $($js_name)?),
::dioxus_core::AttributeValue::listener(move |e: ::dioxus_core::Event<crate::PlatformEventData>| {
_f(e.map(|e|e.into())).spawn();
}),
None,
false,
).into()
}
)*
};
(@name $name:ident $js_name:literal) => {
$js_name
};
(@name $name:ident) => {
stringify!($name)
};
}
static EVENT_CONVERTER: RwLock<Option<Box<dyn HtmlEventConverter>>> = RwLock::new(None);
#[inline]
pub fn set_event_converter(converter: Box<dyn HtmlEventConverter>) {
*EVENT_CONVERTER.write().unwrap() = Some(converter);
}
#[inline]
pub(crate) fn with_event_converter<F, R>(f: F) -> R
where
F: FnOnce(&dyn HtmlEventConverter) -> R,
{
let converter = EVENT_CONVERTER.read().unwrap();
f(converter.as_ref().unwrap().as_ref())
}
pub struct PlatformEventData {
event: Box<dyn Any>,
}
impl PlatformEventData {
pub fn new(event: Box<dyn Any>) -> Self {
Self { event }
}
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.event.downcast_ref::<T>()
}
pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.event.downcast_mut::<T>()
}
pub fn into_inner<T: 'static>(self) -> Option<T> {
self.event.downcast::<T>().ok().map(|e| *e)
}
}
pub trait HtmlEventConverter: Send + Sync {
fn convert_animation_data(&self, event: &PlatformEventData) -> AnimationData;
fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData;
fn convert_composition_data(&self, event: &PlatformEventData) -> CompositionData;
fn convert_drag_data(&self, event: &PlatformEventData) -> DragData;
fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData;
fn convert_form_data(&self, event: &PlatformEventData) -> FormData;
fn convert_image_data(&self, event: &PlatformEventData) -> ImageData;
fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData;
fn convert_media_data(&self, event: &PlatformEventData) -> MediaData;
fn convert_mounted_data(&self, event: &PlatformEventData) -> MountedData;
fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData;
fn convert_pointer_data(&self, event: &PlatformEventData) -> PointerData;
fn convert_scroll_data(&self, event: &PlatformEventData) -> ScrollData;
fn convert_selection_data(&self, event: &PlatformEventData) -> SelectionData;
fn convert_toggle_data(&self, event: &PlatformEventData) -> ToggleData;
fn convert_touch_data(&self, event: &PlatformEventData) -> TouchData;
fn convert_transition_data(&self, event: &PlatformEventData) -> TransitionData;
fn convert_wheel_data(&self, event: &PlatformEventData) -> WheelData;
}
impl From<&PlatformEventData> for AnimationData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_animation_data(val))
}
}
impl From<&PlatformEventData> for ClipboardData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_clipboard_data(val))
}
}
impl From<&PlatformEventData> for CompositionData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_composition_data(val))
}
}
impl From<&PlatformEventData> for DragData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_drag_data(val))
}
}
impl From<&PlatformEventData> for FocusData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_focus_data(val))
}
}
impl From<&PlatformEventData> for FormData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_form_data(val))
}
}
impl From<&PlatformEventData> for ImageData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_image_data(val))
}
}
impl From<&PlatformEventData> for KeyboardData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_keyboard_data(val))
}
}
impl From<&PlatformEventData> for MediaData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_media_data(val))
}
}
impl From<&PlatformEventData> for MountedData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_mounted_data(val))
}
}
impl From<&PlatformEventData> for MouseData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_mouse_data(val))
}
}
impl From<&PlatformEventData> for PointerData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_pointer_data(val))
}
}
impl From<&PlatformEventData> for ScrollData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_scroll_data(val))
}
}
impl From<&PlatformEventData> for SelectionData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_selection_data(val))
}
}
impl From<&PlatformEventData> for ToggleData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_toggle_data(val))
}
}
impl From<&PlatformEventData> for TouchData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_touch_data(val))
}
}
impl From<&PlatformEventData> for TransitionData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_transition_data(val))
}
}
impl From<&PlatformEventData> for WheelData {
fn from(val: &PlatformEventData) -> Self {
with_event_converter(|c| c.convert_wheel_data(val))
}
}
mod animation;
mod clipboard;
mod composition;
mod drag;
mod focus;
mod form;
mod image;
mod keyboard;
mod media;
mod mounted;
mod mouse;
mod pointer;
mod scroll;
mod selection;
mod toggle;
mod touch;
mod transition;
mod wheel;
pub use animation::*;
pub use clipboard::*;
pub use composition::*;
pub use drag::*;
pub use focus::*;
pub use form::*;
pub use image::*;
pub use keyboard::*;
pub use media::*;
pub use mounted::*;
pub use mouse::*;
pub use pointer::*;
pub use scroll::*;
pub use selection::*;
pub use toggle::*;
pub use touch::*;
pub use transition::*;
pub use wheel::*;
pub fn event_bubbles(evt: &str) -> bool {
match evt {
"copy" => true,
"cut" => true,
"paste" => true,
"compositionend" => true,
"compositionstart" => true,
"compositionupdate" => true,
"keydown" => true,
"keypress" => true,
"keyup" => true,
"focus" => false,
"focusout" => true,
"focusin" => true,
"blur" => false,
"change" => true,
"input" => true,
"invalid" => true,
"reset" => true,
"submit" => true,
"click" => true,
"contextmenu" => true,
"doubleclick" => true,
"dblclick" => true,
"drag" => true,
"dragend" => true,
"dragenter" => false,
"dragexit" => false,
"dragleave" => true,
"dragover" => true,
"dragstart" => true,
"drop" => true,
"mousedown" => true,
"mouseenter" => false,
"mouseleave" => false,
"mousemove" => true,
"mouseout" => true,
"scroll" => false,
"mouseover" => true,
"mouseup" => true,
"pointerdown" => true,
"pointermove" => true,
"pointerup" => true,
"pointercancel" => true,
"gotpointercapture" => true,
"lostpointercapture" => true,
"pointerenter" => false,
"pointerleave" => false,
"pointerover" => true,
"pointerout" => true,
"select" => true,
"touchcancel" => true,
"touchend" => true,
"touchmove" => true,
"touchstart" => true,
"wheel" => true,
"abort" => false,
"canplay" => false,
"canplaythrough" => false,
"durationchange" => false,
"emptied" => false,
"encrypted" => true,
"ended" => false,
"error" => false,
"loadeddata" => false,
"loadedmetadata" => false,
"loadstart" => false,
"load" => false,
"pause" => false,
"play" => false,
"playing" => false,
"progress" => false,
"ratechange" => false,
"seeked" => false,
"seeking" => false,
"stalled" => false,
"suspend" => false,
"timeupdate" => false,
"volumechange" => false,
"waiting" => false,
"animationstart" => true,
"animationend" => true,
"animationiteration" => true,
"transitionend" => true,
"toggle" => true,
"mounted" => false,
_ => true,
}
}
#[doc(hidden)]
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);
}
}