diff --git a/packages/core-types/src/bubbles.rs b/packages/core-types/src/bubbles.rs index eefeef6b5..e34f34588 100644 --- a/packages/core-types/src/bubbles.rs +++ b/packages/core-types/src/bubbles.rs @@ -10,6 +10,7 @@ /// in their definition, which gets passed as part of the mutations. pub fn event_bubbles(evt: &str) -> bool { match evt { + "cancel" => false, "copy" => true, "cut" => true, "paste" => true, diff --git a/packages/desktop/src/events.rs b/packages/desktop/src/events.rs index 974581e99..3d863b50e 100644 --- a/packages/desktop/src/events.rs +++ b/packages/desktop/src/events.rs @@ -17,6 +17,14 @@ impl HtmlEventConverter for SerializedHtmlEventConverter { .into() } + fn convert_cancel_data(&self, event: &PlatformEventData) -> CancelData { + event + .downcast::() + .cloned() + .unwrap() + .into() + } + fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData { event .downcast::() diff --git a/packages/html/src/events/cancel.rs b/packages/html/src/events/cancel.rs new file mode 100644 index 000000000..ff36d5e35 --- /dev/null +++ b/packages/html/src/events/cancel.rs @@ -0,0 +1,88 @@ +use dioxus_core::Event; + +pub type CancelEvent = Event; + +pub struct CancelData { + inner: Box, +} + +impl From for CancelData { + fn from(e: E) -> Self { + Self { inner: Box::new(e) } + } +} + +impl std::fmt::Debug for CancelData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CancelData").finish() + } +} + +impl PartialEq for CancelData { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl CancelData { + /// Create a new CancelData + pub fn new(inner: impl HasCancelData + 'static) -> Self { + Self { + inner: Box::new(inner), + } + } + + /// Downcast this event to a concrete event type + #[inline(always)] + pub fn downcast(&self) -> Option<&T> { + self.inner.as_any().downcast_ref::() + } +} + +#[cfg(feature = "serialize")] +/// A serialized version of CancelData +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)] +pub struct SerializedCancelData {} + +#[cfg(feature = "serialize")] +impl From<&CancelData> for SerializedCancelData { + fn from(_: &CancelData) -> Self { + Self {} + } +} + +#[cfg(feature = "serialize")] +impl HasCancelData for SerializedCancelData { + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + +#[cfg(feature = "serialize")] +impl serde::Serialize for CancelData { + fn serialize(&self, serializer: S) -> Result { + SerializedCancelData::from(self).serialize(serializer) + } +} + +#[cfg(feature = "serialize")] +impl<'de> serde::Deserialize<'de> for CancelData { + fn deserialize>(deserializer: D) -> Result { + let data = SerializedCancelData::deserialize(deserializer)?; + Ok(Self { + inner: Box::new(data), + }) + } +} + +pub trait HasCancelData: std::any::Any { + /// return self as Any + fn as_any(&self) -> &dyn std::any::Any; +} + +impl_event! { + CancelData; + + /// oncancel + oncancel +} diff --git a/packages/html/src/events/mod.rs b/packages/html/src/events/mod.rs index d76045260..63333bf09 100644 --- a/packages/html/src/events/mod.rs +++ b/packages/html/src/events/mod.rs @@ -115,6 +115,8 @@ impl PlatformEventData { pub trait HtmlEventConverter: Send + Sync { /// Convert a general event to an animation data event fn convert_animation_data(&self, event: &PlatformEventData) -> AnimationData; + /// Convert a general event to a cancel data event + fn convert_cancel_data(&self, event: &PlatformEventData) -> CancelData; /// Convert a general event to a clipboard data event fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData; /// Convert a general event to a composition data event @@ -161,6 +163,12 @@ impl From<&PlatformEventData> for AnimationData { } } +impl From<&PlatformEventData> for CancelData { + fn from(val: &PlatformEventData) -> Self { + with_event_converter(|c| c.convert_cancel_data(val)) + } +} + impl From<&PlatformEventData> for ClipboardData { fn from(val: &PlatformEventData) -> Self { with_event_converter(|c| c.convert_clipboard_data(val)) @@ -276,6 +284,7 @@ impl From<&PlatformEventData> for WheelData { } mod animation; +mod cancel; mod clipboard; mod composition; mod drag; @@ -297,6 +306,7 @@ mod visible; mod wheel; pub use animation::*; +pub use cancel::*; pub use clipboard::*; pub use composition::*; pub use drag::*; diff --git a/packages/html/src/transit.rs b/packages/html/src/transit.rs index b5386220e..ace2d4bcd 100644 --- a/packages/html/src/transit.rs +++ b/packages/html/src/transit.rs @@ -65,6 +65,9 @@ fn deserialize_raw(name: &str, data: &serde_json::Value) -> Result Cancel(de(data)?), + // Mouse "click" | "contextmenu" | "dblclick" | "doubleclick" | "mousedown" | "mouseenter" | "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => Mouse(de(data)?), @@ -154,6 +157,7 @@ impl HtmlEvent { #[serde(untagged)] #[non_exhaustive] pub enum EventData { + Cancel(SerializedCancelData), Mouse(SerializedMouseData), Clipboard(SerializedClipboardData), Composition(SerializedCompositionData), @@ -179,6 +183,9 @@ pub enum EventData { impl EventData { pub fn into_any(self) -> Rc { match self { + EventData::Cancel(data) => { + Rc::new(PlatformEventData::new(Box::new(data))) as Rc + } EventData::Mouse(data) => { Rc::new(PlatformEventData::new(Box::new(data))) as Rc } @@ -291,6 +298,14 @@ impl HtmlEventConverter for SerializedHtmlEventConverter { .into() } + fn convert_cancel_data(&self, event: &PlatformEventData) -> CancelData { + event + .downcast::() + .cloned() + .unwrap() + .into() + } + fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData { event .downcast::() diff --git a/packages/liveview/src/events.rs b/packages/liveview/src/events.rs index 1125c8712..27e42d93b 100644 --- a/packages/liveview/src/events.rs +++ b/packages/liveview/src/events.rs @@ -15,6 +15,14 @@ impl HtmlEventConverter for SerializedHtmlEventConverter { .into() } + fn convert_cancel_data(&self, event: &PlatformEventData) -> CancelData { + event + .downcast::() + .cloned() + .unwrap() + .into() + } + fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData { event .downcast::() diff --git a/packages/native-dom/src/events.rs b/packages/native-dom/src/events.rs index 0f18f646e..ad987a349 100644 --- a/packages/native-dom/src/events.rs +++ b/packages/native-dom/src/events.rs @@ -5,11 +5,11 @@ use dioxus_html::{ point_interaction::{ InteractionElementOffset, InteractionLocation, ModifiersInteraction, PointerInteraction, }, - AnimationData, ClipboardData, CompositionData, DragData, FocusData, FormData, FormValue, - HasFileData, HasFocusData, HasFormData, HasKeyboardData, HasMouseData, HtmlEventConverter, - ImageData, KeyboardData, MediaData, MountedData, MouseData, PlatformEventData, PointerData, - ResizeData, ScrollData, SelectionData, ToggleData, TouchData, TransitionData, VisibleData, - WheelData, + AnimationData, CancelData, ClipboardData, CompositionData, DragData, FocusData, FormData, + FormValue, HasFileData, HasFocusData, HasFormData, HasKeyboardData, HasMouseData, + HtmlEventConverter, ImageData, KeyboardData, MediaData, MountedData, MouseData, + PlatformEventData, PointerData, ResizeData, ScrollData, SelectionData, ToggleData, TouchData, + TransitionData, VisibleData, WheelData, }; use keyboard_types::{Code, Key, Location, Modifiers}; use std::any::Any; @@ -18,6 +18,10 @@ use std::collections::HashMap; pub struct NativeConverter {} impl HtmlEventConverter for NativeConverter { + fn convert_cancel_data(&self, _event: &PlatformEventData) -> CancelData { + todo!("todo: convert_cancel_data in dioxus-native. requires support in blitz") + } + fn convert_form_data(&self, event: &PlatformEventData) -> FormData { event.downcast::().unwrap().clone().into() } diff --git a/packages/web/src/events/cancel.rs b/packages/web/src/events/cancel.rs new file mode 100644 index 000000000..c7cd85a09 --- /dev/null +++ b/packages/web/src/events/cancel.rs @@ -0,0 +1,17 @@ +use super::{Synthetic, WebEventExt}; +use dioxus_html::HasCancelData; + +impl HasCancelData for Synthetic { + fn as_any(&self) -> &dyn std::any::Any { + &self.event + } +} + +impl WebEventExt for dioxus_html::CancelData { + type WebEvent = web_sys::Event; + + #[inline(always)] + fn try_as_web_event(&self) -> Option { + self.downcast::().cloned() + } +} diff --git a/packages/web/src/events/mod.rs b/packages/web/src/events/mod.rs index 7bdfaebf5..cb5659471 100644 --- a/packages/web/src/events/mod.rs +++ b/packages/web/src/events/mod.rs @@ -7,6 +7,7 @@ use wasm_bindgen::JsCast; use web_sys::{Document, Element, Event}; mod animation; +mod cancel; mod clipboard; mod composition; mod drag; @@ -60,6 +61,14 @@ impl HtmlEventConverter for WebEventConverter { Synthetic::::from(downcast_event(event).raw.clone()).into() } + #[inline(always)] + fn convert_cancel_data( + &self, + event: &dioxus_html::PlatformEventData, + ) -> dioxus_html::CancelData { + Synthetic::new(downcast_event(event).raw.clone()).into() + } + #[inline(always)] fn convert_clipboard_data( &self,