Fix autofill event downcast - ignore events of the wrong type (#5379)
* fix autofill events * ignore the wrong type of event like we do in desktop * check the event type before dispatch instead of panicing on downcast * clean up conversion * remove example * pull out shared event list * pull in deserialize_raw * unified event list * prettier comment * restore test * restore alias * normal doc comments * move over comments * minimize diff * remove alias, was moved into the macro
This commit is contained in:
1 parent
610ee8107f
commit
d8026f8824
27 files changed
+596
-960
No files matched your search
@@ -130,16 +130,3 @@ pub trait HasAnimationData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! [
|
|
||||||
AnimationData;
|
|
||||||
|
|
||||||
/// onanimationstart
|
|
||||||
onanimationstart
|
|
||||||
|
|
||||||
/// onanimationend
|
|
||||||
onanimationend
|
|
||||||
|
|
||||||
/// onanimationiteration
|
|
||||||
onanimationiteration
|
|
||||||
];
|
|
||||||
@@ -79,10 +79,3 @@ pub trait HasCancelData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
CancelData;
|
|
||||||
|
|
||||||
/// oncancel
|
|
||||||
oncancel
|
|
||||||
}
|
|
||||||
@@ -79,16 +79,3 @@ pub trait HasClipboardData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event![
|
|
||||||
ClipboardData;
|
|
||||||
|
|
||||||
/// oncopy
|
|
||||||
oncopy
|
|
||||||
|
|
||||||
/// oncut
|
|
||||||
oncut
|
|
||||||
|
|
||||||
/// onpaste
|
|
||||||
onpaste
|
|
||||||
];
|
|
||||||
@@ -94,16 +94,3 @@ pub trait HasCompositionData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! [
|
|
||||||
CompositionData;
|
|
||||||
|
|
||||||
/// oncompositionstart
|
|
||||||
oncompositionstart
|
|
||||||
|
|
||||||
/// oncompositionend
|
|
||||||
oncompositionend
|
|
||||||
|
|
||||||
/// oncompositionupdate
|
|
||||||
oncompositionupdate
|
|
||||||
];
|
|
||||||
@@ -226,31 +226,3 @@ pub trait HasDragData: HasMouseData + crate::HasFileData + crate::HasDataTransfe
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
DragData;
|
|
||||||
|
|
||||||
/// ondrag
|
|
||||||
ondrag
|
|
||||||
|
|
||||||
/// ondragend
|
|
||||||
ondragend
|
|
||||||
|
|
||||||
/// ondragenter
|
|
||||||
ondragenter
|
|
||||||
|
|
||||||
/// ondragexit
|
|
||||||
ondragexit
|
|
||||||
|
|
||||||
/// ondragleave
|
|
||||||
ondragleave
|
|
||||||
|
|
||||||
/// ondragover
|
|
||||||
ondragover
|
|
||||||
|
|
||||||
/// ondragstart
|
|
||||||
ondragstart
|
|
||||||
|
|
||||||
/// ondrop
|
|
||||||
ondrop
|
|
||||||
}
|
|
||||||
@@ -79,19 +79,3 @@ pub trait HasFocusData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! [
|
|
||||||
FocusData;
|
|
||||||
|
|
||||||
/// onfocus
|
|
||||||
onfocus
|
|
||||||
|
|
||||||
// onfocusout
|
|
||||||
onfocusout
|
|
||||||
|
|
||||||
// onfocusin
|
|
||||||
onfocusin
|
|
||||||
|
|
||||||
/// onblur
|
|
||||||
onblur
|
|
||||||
];
|
|
||||||
@@ -346,65 +346,3 @@ mod serialize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
FormData;
|
|
||||||
|
|
||||||
/// onchange
|
|
||||||
onchange
|
|
||||||
|
|
||||||
/// The `oninput` event is fired when the value of a `<input>`, `<select>`, or `<textarea>` element is changed.
|
|
||||||
///
|
|
||||||
/// There are two main approaches to updating your input element:
|
|
||||||
/// 1) Controlled inputs directly update the value of the input element as the user interacts with the element
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use dioxus::prelude::*;
|
|
||||||
///
|
|
||||||
/// fn App() -> Element {
|
|
||||||
/// let mut value = use_signal(|| "hello world".to_string());
|
|
||||||
///
|
|
||||||
/// rsx! {
|
|
||||||
/// input {
|
|
||||||
/// // We directly set the value of the input element to our value signal
|
|
||||||
/// value: "{value}",
|
|
||||||
/// // The `oninput` event handler will run every time the user changes the value of the input element
|
|
||||||
/// // We can set the `value` signal to the new value of the input element
|
|
||||||
/// oninput: move |event| value.set(event.value())
|
|
||||||
/// }
|
|
||||||
/// // Since this is a controlled input, we can also update the value of the input element directly
|
|
||||||
/// button {
|
|
||||||
/// onclick: move |_| value.write().clear(),
|
|
||||||
/// "Clear"
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// 2) Uncontrolled inputs just read the value of the input element as it changes
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use dioxus::prelude::*;
|
|
||||||
///
|
|
||||||
/// fn App() -> Element {
|
|
||||||
/// rsx! {
|
|
||||||
/// input {
|
|
||||||
/// // In uncontrolled inputs, we don't set the value of the input element directly
|
|
||||||
/// // But you can still read the value of the input element
|
|
||||||
/// oninput: move |event| println!("{}", event.value()),
|
|
||||||
/// }
|
|
||||||
/// // Since we don't directly control the value of the input element, we can't easily modify it
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
oninput
|
|
||||||
|
|
||||||
/// oninvalid
|
|
||||||
oninvalid
|
|
||||||
|
|
||||||
/// onreset
|
|
||||||
onreset
|
|
||||||
|
|
||||||
/// onsubmit
|
|
||||||
onsubmit
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,448 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! with_html_event_groups {
|
||||||
|
($macro:ident) => {
|
||||||
|
$macro! {
|
||||||
|
enum Event {
|
||||||
|
#[convert = convert_animation_data]
|
||||||
|
#[events = [
|
||||||
|
onanimationstart => animationstart,
|
||||||
|
onanimationend => animationend,
|
||||||
|
onanimationiteration => animationiteration,
|
||||||
|
]]
|
||||||
|
Animation(AnimationData),
|
||||||
|
|
||||||
|
#[convert = convert_cancel_data]
|
||||||
|
#[events = [
|
||||||
|
oncancel => cancel,
|
||||||
|
]]
|
||||||
|
Cancel(CancelData),
|
||||||
|
|
||||||
|
#[convert = convert_clipboard_data]
|
||||||
|
#[events = [
|
||||||
|
oncopy => copy,
|
||||||
|
oncut => cut,
|
||||||
|
onpaste => paste,
|
||||||
|
]]
|
||||||
|
Clipboard(ClipboardData),
|
||||||
|
|
||||||
|
#[convert = convert_composition_data]
|
||||||
|
#[events = [
|
||||||
|
oncompositionstart => compositionstart,
|
||||||
|
oncompositionend => compositionend,
|
||||||
|
oncompositionupdate => compositionupdate,
|
||||||
|
]]
|
||||||
|
Composition(CompositionData),
|
||||||
|
|
||||||
|
#[convert = convert_drag_data]
|
||||||
|
#[events = [
|
||||||
|
ondrag => drag,
|
||||||
|
ondragend => dragend,
|
||||||
|
ondragenter => dragenter,
|
||||||
|
ondragexit => dragexit,
|
||||||
|
ondragleave => dragleave,
|
||||||
|
ondragover => dragover,
|
||||||
|
ondragstart => dragstart,
|
||||||
|
ondrop => drop,
|
||||||
|
]]
|
||||||
|
Drag(DragData),
|
||||||
|
|
||||||
|
#[convert = convert_focus_data]
|
||||||
|
#[events = [
|
||||||
|
onfocus => focus,
|
||||||
|
onfocusout => focusout,
|
||||||
|
onfocusin => focusin,
|
||||||
|
onblur => blur,
|
||||||
|
]]
|
||||||
|
Focus(FocusData),
|
||||||
|
|
||||||
|
#[convert = convert_form_data]
|
||||||
|
#[events = [
|
||||||
|
onchange => change,
|
||||||
|
/// The `oninput` event is fired when the value of a `<input>`, `<select>`, or `<textarea>` element is changed.
|
||||||
|
///
|
||||||
|
/// There are two main approaches to updating your input element:
|
||||||
|
/// 1) Controlled inputs directly update the value of the input element as the user interacts with the element
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use dioxus::prelude::*;
|
||||||
|
///
|
||||||
|
/// fn App() -> Element {
|
||||||
|
/// let mut value = use_signal(|| "hello world".to_string());
|
||||||
|
///
|
||||||
|
/// rsx! {
|
||||||
|
/// input {
|
||||||
|
/// value: "{value}",
|
||||||
|
/// oninput: move |event| value.set(event.value())
|
||||||
|
/// }
|
||||||
|
/// button {
|
||||||
|
/// onclick: move |_| value.write().clear(),
|
||||||
|
/// "Clear"
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 2) Uncontrolled inputs just read the value of the input element as it changes
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use dioxus::prelude::*;
|
||||||
|
///
|
||||||
|
/// fn App() -> Element {
|
||||||
|
/// rsx! {
|
||||||
|
/// input {
|
||||||
|
/// oninput: move |event| println!("{}", event.value()),
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
oninput => input,
|
||||||
|
oninvalid => invalid,
|
||||||
|
onreset => reset,
|
||||||
|
onsubmit => submit,
|
||||||
|
]]
|
||||||
|
Form(FormData),
|
||||||
|
|
||||||
|
#[convert = convert_image_data]
|
||||||
|
#[events = [
|
||||||
|
onerror => error,
|
||||||
|
onload => load,
|
||||||
|
]]
|
||||||
|
Image(ImageData),
|
||||||
|
|
||||||
|
#[convert = convert_keyboard_data]
|
||||||
|
#[events = [
|
||||||
|
onkeydown => keydown,
|
||||||
|
onkeypress => keypress,
|
||||||
|
onkeyup => keyup,
|
||||||
|
]]
|
||||||
|
Keyboard(KeyboardData),
|
||||||
|
|
||||||
|
#[convert = convert_media_data]
|
||||||
|
#[events = [
|
||||||
|
onabort => abort,
|
||||||
|
oncanplay => canplay,
|
||||||
|
oncanplaythrough => canplaythrough,
|
||||||
|
ondurationchange => durationchange,
|
||||||
|
onemptied => emptied,
|
||||||
|
onencrypted => encrypted,
|
||||||
|
onended => ended,
|
||||||
|
onloadeddata => loadeddata,
|
||||||
|
onloadedmetadata => loadedmetadata,
|
||||||
|
onloadstart => loadstart,
|
||||||
|
onpause => pause,
|
||||||
|
onplay => play,
|
||||||
|
onplaying => playing,
|
||||||
|
onprogress => progress,
|
||||||
|
onratechange => ratechange,
|
||||||
|
onseeked => seeked,
|
||||||
|
onseeking => seeking,
|
||||||
|
onstalled => stalled,
|
||||||
|
onsuspend => suspend,
|
||||||
|
ontimeupdate => timeupdate,
|
||||||
|
onvolumechange => volumechange,
|
||||||
|
onwaiting => waiting,
|
||||||
|
]]
|
||||||
|
#[raw = [interruptbegin, interruptend, loadend, timeout]]
|
||||||
|
Media(MediaData),
|
||||||
|
|
||||||
|
#[convert = convert_mounted_data]
|
||||||
|
#[events = [
|
||||||
|
#[doc(alias = "ref")]
|
||||||
|
#[doc(alias = "createRef")]
|
||||||
|
#[doc(alias = "useRef")]
|
||||||
|
/// The onmounted event is fired when the element is first added to the DOM. This event gives you a [`MountedData`] object and lets you interact with the raw DOM element.
|
||||||
|
///
|
||||||
|
/// This event is fired once per element. If you need to access the element multiple times, you can store the [`MountedData`] object in a [`use_signal`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_signal.html) hook and use it as needed.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust, no_run
|
||||||
|
/// # use dioxus::prelude::*;
|
||||||
|
/// fn App() -> Element {
|
||||||
|
/// let mut header_element = use_signal(|| None);
|
||||||
|
///
|
||||||
|
/// rsx! {
|
||||||
|
/// div {
|
||||||
|
/// h1 {
|
||||||
|
/// // The onmounted event will run the first time the h1 element is mounted
|
||||||
|
/// onmounted: move |element| header_element.set(Some(element.data())),
|
||||||
|
/// "Scroll to top example"
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// for i in 0..100 {
|
||||||
|
/// div { "Item {i}" }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// button {
|
||||||
|
/// // When you click the button, if the header element has been mounted, we scroll to that element
|
||||||
|
/// onclick: move |_| async move {
|
||||||
|
/// if let Some(header) = header_element.cloned() {
|
||||||
|
/// let _ = header.scroll_to(ScrollBehavior::Smooth).await;
|
||||||
|
/// }
|
||||||
|
/// },
|
||||||
|
/// "Scroll to top"
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The `MountedData` struct contains cross platform APIs that work on the desktop, mobile, liveview and web platforms. For the web platform, you can also downcast the `MountedData` event to the `web-sys::Element` type for more web specific APIs:
|
||||||
|
///
|
||||||
|
/// ```rust, ignore
|
||||||
|
/// use dioxus::prelude::*;
|
||||||
|
/// use dioxus_web::WebEventExt; // provides [`as_web_event()`] method
|
||||||
|
///
|
||||||
|
/// fn App() -> Element {
|
||||||
|
/// rsx! {
|
||||||
|
/// div {
|
||||||
|
/// id: "some-id",
|
||||||
|
/// onmounted: move |element| {
|
||||||
|
/// // You can use the web_event trait to downcast the element to a web specific event. For the mounted event, this will be a web_sys::Element
|
||||||
|
/// let web_sys_element = element.as_web_event();
|
||||||
|
/// assert_eq!(web_sys_element.id(), "some-id");
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
onmounted => mounted,
|
||||||
|
]]
|
||||||
|
Mounted(MountedData),
|
||||||
|
|
||||||
|
#[convert = convert_mouse_data]
|
||||||
|
#[events = [
|
||||||
|
/// Execute a callback when a button is clicked.
|
||||||
|
///
|
||||||
|
/// ## Description
|
||||||
|
///
|
||||||
|
/// An element receives a click event when a pointing device button (such as a mouse's primary mouse button)
|
||||||
|
/// is both pressed and released while the pointer is located inside the element.
|
||||||
|
///
|
||||||
|
/// - Bubbles: Yes
|
||||||
|
/// - Cancelable: Yes
|
||||||
|
/// - Interface(InteData): [`MouseEvent`]
|
||||||
|
///
|
||||||
|
/// If the button is pressed on one element and the pointer is moved outside the element before the button
|
||||||
|
/// is released, the event is fired on the most specific ancestor element that contained both elements.
|
||||||
|
/// `click` fires after both the `mousedown` and `mouseup` events have fired, in that order.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```rust, ignore
|
||||||
|
/// rsx!( button { onclick: move |_| tracing::info!("Clicked!"), "click me" } )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Reference
|
||||||
|
/// - <https://www.w3schools.com/tags/ev_onclick.asp>
|
||||||
|
/// - <https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event>
|
||||||
|
onclick => click,
|
||||||
|
oncontextmenu => contextmenu,
|
||||||
|
#[deprecated(since = "0.5.0", note = "use ondoubleclick instead")]
|
||||||
|
ondblclick => dblclick,
|
||||||
|
#[doc(alias = "ondblclick")]
|
||||||
|
ondoubleclick => dblclick,
|
||||||
|
onmousedown => mousedown,
|
||||||
|
onmouseenter => mouseenter,
|
||||||
|
onmouseleave => mouseleave,
|
||||||
|
onmousemove => mousemove,
|
||||||
|
onmouseout => mouseout,
|
||||||
|
/// Triggered when the users's mouse hovers over an element.
|
||||||
|
onmouseover => mouseover,
|
||||||
|
onmouseup => mouseup,
|
||||||
|
]]
|
||||||
|
#[raw = [doubleclick]]
|
||||||
|
Mouse(MouseData),
|
||||||
|
|
||||||
|
#[convert = convert_pointer_data]
|
||||||
|
#[events = [
|
||||||
|
onpointerdown => pointerdown,
|
||||||
|
onpointermove => pointermove,
|
||||||
|
onpointerup => pointerup,
|
||||||
|
onpointercancel => pointercancel,
|
||||||
|
ongotpointercapture => gotpointercapture,
|
||||||
|
onlostpointercapture => lostpointercapture,
|
||||||
|
onpointerenter => pointerenter,
|
||||||
|
onpointerleave => pointerleave,
|
||||||
|
onpointerover => pointerover,
|
||||||
|
onpointerout => pointerout,
|
||||||
|
onauxclick => auxclick,
|
||||||
|
]]
|
||||||
|
#[raw = [pointerlockchange, pointerlockerror]]
|
||||||
|
Pointer(PointerData),
|
||||||
|
|
||||||
|
#[convert = convert_resize_data]
|
||||||
|
#[events = [
|
||||||
|
onresize => resize,
|
||||||
|
]]
|
||||||
|
Resize(ResizeData),
|
||||||
|
|
||||||
|
#[convert = convert_scroll_data]
|
||||||
|
#[events = [
|
||||||
|
onscroll => scroll,
|
||||||
|
onscrollend => scrollend,
|
||||||
|
]]
|
||||||
|
Scroll(ScrollData),
|
||||||
|
|
||||||
|
#[convert = convert_selection_data]
|
||||||
|
#[events = [
|
||||||
|
onselect => select,
|
||||||
|
onselectstart => selectstart,
|
||||||
|
onselectionchange => selectionchange,
|
||||||
|
]]
|
||||||
|
Selection(SelectionData),
|
||||||
|
|
||||||
|
#[convert = convert_toggle_data]
|
||||||
|
#[events = [
|
||||||
|
ontoggle => toggle,
|
||||||
|
onbeforetoggle => beforetoggle,
|
||||||
|
]]
|
||||||
|
Toggle(ToggleData),
|
||||||
|
|
||||||
|
#[convert = convert_touch_data]
|
||||||
|
#[events = [
|
||||||
|
ontouchstart => touchstart,
|
||||||
|
ontouchmove => touchmove,
|
||||||
|
ontouchend => touchend,
|
||||||
|
ontouchcancel => touchcancel,
|
||||||
|
]]
|
||||||
|
Touch(TouchData),
|
||||||
|
|
||||||
|
#[convert = convert_transition_data]
|
||||||
|
#[events = [
|
||||||
|
ontransitionend => transitionend,
|
||||||
|
]]
|
||||||
|
Transition(TransitionData),
|
||||||
|
|
||||||
|
#[convert = convert_visible_data]
|
||||||
|
#[events = [
|
||||||
|
onvisible => visible,
|
||||||
|
]]
|
||||||
|
Visible(VisibleData),
|
||||||
|
|
||||||
|
#[convert = convert_wheel_data]
|
||||||
|
#[events = [
|
||||||
|
/// Called when the mouse wheel is rotated over an element.
|
||||||
|
onwheel => wheel,
|
||||||
|
]]
|
||||||
|
Wheel(WheelData),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! expand_html_event_converter {
|
||||||
|
(
|
||||||
|
enum Event {
|
||||||
|
$(
|
||||||
|
#[convert = $converter:ident]
|
||||||
|
#[events = [
|
||||||
|
$(
|
||||||
|
$( #[$attr:meta] )*
|
||||||
|
$name:ident => $raw:ident,
|
||||||
|
)*
|
||||||
|
]]
|
||||||
|
$(#[raw = [$($raw_only:ident),* $(,)?]])?
|
||||||
|
$group:ident($data:ident),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
/// A converter between a platform specific event and a general event. All code in a renderer that has a large binary size should be placed in this trait. Each of these functions should be snipped in high levels of optimization.
|
||||||
|
pub trait HtmlEventConverter: Send + Sync {
|
||||||
|
$(
|
||||||
|
fn $converter(&self, event: &PlatformEventData) -> $data;
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
impl From<&PlatformEventData> for $data {
|
||||||
|
fn from(val: &PlatformEventData) -> Self {
|
||||||
|
with_event_converter(|c| c.$converter(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serialize")]
|
||||||
|
macro_rules! expand_html_event_deserialize {
|
||||||
|
(
|
||||||
|
enum Event {
|
||||||
|
$(
|
||||||
|
#[convert = $converter:ident]
|
||||||
|
#[events = [
|
||||||
|
$(
|
||||||
|
$( #[$attr:meta] )*
|
||||||
|
$name:ident => $raw:ident,
|
||||||
|
)*
|
||||||
|
]]
|
||||||
|
$(#[raw = [$($raw_only:ident),* $(,)?]])?
|
||||||
|
$group:ident($data:ident),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
pub(crate) fn deserialize_raw_event(
|
||||||
|
name: &str,
|
||||||
|
data: &serde_json::Value,
|
||||||
|
) -> Result<Option<crate::transit::EventData>, serde_json::Error> {
|
||||||
|
#[inline]
|
||||||
|
fn de<'de, F>(f: &'de serde_json::Value) -> Result<F, serde_json::Error>
|
||||||
|
where
|
||||||
|
F: serde::Deserialize<'de>,
|
||||||
|
{
|
||||||
|
F::deserialize(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match name {
|
||||||
|
$(
|
||||||
|
$( stringify!($raw) )|* $($(| stringify!($raw_only))*)? => {
|
||||||
|
Some(expand_html_event_deserialize!(@deserialize $group, data))
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(@deserialize Mounted, $data:ident) => {
|
||||||
|
crate::transit::EventData::Mounted
|
||||||
|
};
|
||||||
|
(@deserialize $group:ident, $data:ident) => {
|
||||||
|
crate::transit::EventData::$group(de($data)?)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! expand_html_event_listeners {
|
||||||
|
(
|
||||||
|
enum Event {
|
||||||
|
$(
|
||||||
|
#[convert = $converter:ident]
|
||||||
|
#[events = [
|
||||||
|
$(
|
||||||
|
$( #[$attr:meta] )*
|
||||||
|
$name:ident => $raw:ident,
|
||||||
|
)*
|
||||||
|
]]
|
||||||
|
$(#[raw = [$($raw_only:ident),* $(,)?]])?
|
||||||
|
$group:ident($data:ident),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
impl_event! {
|
||||||
|
$data;
|
||||||
|
$(
|
||||||
|
#[doc = concat!(stringify!($name))]
|
||||||
|
$( #[$attr] )*
|
||||||
|
$name: concat!("on", stringify!($raw));
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
with_html_event_groups!(expand_html_event_converter);
|
||||||
|
#[cfg(feature = "serialize")]
|
||||||
|
with_html_event_groups!(expand_html_event_deserialize);
|
||||||
|
with_html_event_groups!(expand_html_event_listeners);
|
||||||
@@ -94,13 +94,3 @@ pub trait HasImageData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! [
|
|
||||||
ImageData;
|
|
||||||
|
|
||||||
/// onerror
|
|
||||||
onerror
|
|
||||||
|
|
||||||
/// onload
|
|
||||||
onload
|
|
||||||
];
|
|
||||||
@@ -226,19 +226,6 @@ impl<'de> serde::Deserialize<'de> for KeyboardData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
KeyboardData;
|
|
||||||
|
|
||||||
/// onkeydown
|
|
||||||
onkeydown
|
|
||||||
|
|
||||||
/// onkeypress
|
|
||||||
onkeypress
|
|
||||||
|
|
||||||
/// onkeyup
|
|
||||||
onkeyup
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HasKeyboardData: ModifiersInteraction + std::any::Any {
|
pub trait HasKeyboardData: ModifiersInteraction + std::any::Any {
|
||||||
/// The value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.
|
/// The value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.
|
||||||
fn key(&self) -> Key;
|
fn key(&self) -> Key;
|
||||||
|
|||||||
@@ -78,78 +78,3 @@ pub trait HasMediaData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! [
|
|
||||||
MediaData;
|
|
||||||
|
|
||||||
///abort
|
|
||||||
onabort
|
|
||||||
|
|
||||||
///canplay
|
|
||||||
oncanplay
|
|
||||||
|
|
||||||
///canplaythrough
|
|
||||||
oncanplaythrough
|
|
||||||
|
|
||||||
///durationchange
|
|
||||||
ondurationchange
|
|
||||||
|
|
||||||
///emptied
|
|
||||||
onemptied
|
|
||||||
|
|
||||||
///encrypted
|
|
||||||
onencrypted
|
|
||||||
|
|
||||||
///ended
|
|
||||||
onended
|
|
||||||
|
|
||||||
// todo: this conflicts with Media events
|
|
||||||
// neither have data, so it's okay
|
|
||||||
// ///error
|
|
||||||
// onerror
|
|
||||||
|
|
||||||
///loadeddata
|
|
||||||
onloadeddata
|
|
||||||
|
|
||||||
///loadedmetadata
|
|
||||||
onloadedmetadata
|
|
||||||
|
|
||||||
///loadstart
|
|
||||||
onloadstart
|
|
||||||
|
|
||||||
///pause
|
|
||||||
onpause
|
|
||||||
|
|
||||||
///play
|
|
||||||
onplay
|
|
||||||
|
|
||||||
///playing
|
|
||||||
onplaying
|
|
||||||
|
|
||||||
///progress
|
|
||||||
onprogress
|
|
||||||
|
|
||||||
///ratechange
|
|
||||||
onratechange
|
|
||||||
|
|
||||||
///seeked
|
|
||||||
onseeked
|
|
||||||
|
|
||||||
///seeking
|
|
||||||
onseeking
|
|
||||||
|
|
||||||
///stalled
|
|
||||||
onstalled
|
|
||||||
|
|
||||||
///suspend
|
|
||||||
onsuspend
|
|
||||||
|
|
||||||
///timeupdate
|
|
||||||
ontimeupdate
|
|
||||||
|
|
||||||
///volumechange
|
|
||||||
onvolumechange
|
|
||||||
|
|
||||||
///waiting
|
|
||||||
onwaiting
|
|
||||||
];
|
|
||||||
@@ -8,7 +8,7 @@ macro_rules! impl_event {
|
|||||||
$data:ty;
|
$data:ty;
|
||||||
$(
|
$(
|
||||||
$( #[$attr:meta] )*
|
$( #[$attr:meta] )*
|
||||||
$name:ident $(: $js_name:literal)?
|
$name:ident $( : $js_name:expr )?;
|
||||||
)*
|
)*
|
||||||
) => {
|
) => {
|
||||||
$(
|
$(
|
||||||
@@ -21,9 +21,6 @@ macro_rules! impl_event {
|
|||||||
/// </details>
|
/// </details>
|
||||||
///
|
///
|
||||||
#[doc = include_str!("../../docs/common_event_handler_errors.md")]
|
#[doc = include_str!("../../docs/common_event_handler_errors.md")]
|
||||||
$(
|
|
||||||
#[doc(alias = $js_name)]
|
|
||||||
)?
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn $name<__Marker>(mut _f: impl ::dioxus_core::SuperInto<::dioxus_core::ListenerCallback<$data>, __Marker>) -> ::dioxus_core::Attribute {
|
pub fn $name<__Marker>(mut _f: impl ::dioxus_core::SuperInto<::dioxus_core::ListenerCallback<$data>, __Marker>) -> ::dioxus_core::Attribute {
|
||||||
let event_handler = _f.super_into();
|
let event_handler = _f.super_into();
|
||||||
@@ -60,7 +57,7 @@ macro_rules! impl_event {
|
|||||||
)*
|
)*
|
||||||
};
|
};
|
||||||
|
|
||||||
(@name $name:ident $js_name:literal) => {
|
(@name $name:ident $js_name:expr) => {
|
||||||
$js_name
|
$js_name
|
||||||
};
|
};
|
||||||
(@name $name:ident) => {
|
(@name $name:ident) => {
|
||||||
@@ -111,177 +108,7 @@ impl PlatformEventData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A converter between a platform specific event and a general event. All code in a renderer that has a large binary size should be placed in this trait. Each of these functions should be snipped in high levels of optimization.
|
mod generated;
|
||||||
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
|
|
||||||
fn convert_composition_data(&self, event: &PlatformEventData) -> CompositionData;
|
|
||||||
/// Convert a general event to a drag data event
|
|
||||||
fn convert_drag_data(&self, event: &PlatformEventData) -> DragData;
|
|
||||||
/// Convert a general event to a focus data event
|
|
||||||
fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData;
|
|
||||||
/// Convert a general event to a form data event
|
|
||||||
fn convert_form_data(&self, event: &PlatformEventData) -> FormData;
|
|
||||||
/// Convert a general event to an image data event
|
|
||||||
fn convert_image_data(&self, event: &PlatformEventData) -> ImageData;
|
|
||||||
/// Convert a general event to a keyboard data event
|
|
||||||
fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData;
|
|
||||||
/// Convert a general event to a media data event
|
|
||||||
fn convert_media_data(&self, event: &PlatformEventData) -> MediaData;
|
|
||||||
/// Convert a general event to a mounted data event
|
|
||||||
fn convert_mounted_data(&self, event: &PlatformEventData) -> MountedData;
|
|
||||||
/// Convert a general event to a mouse data event
|
|
||||||
fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData;
|
|
||||||
/// Convert a general event to a pointer data event
|
|
||||||
fn convert_pointer_data(&self, event: &PlatformEventData) -> PointerData;
|
|
||||||
/// Convert a general event to a resize data event
|
|
||||||
fn convert_resize_data(&self, event: &PlatformEventData) -> ResizeData;
|
|
||||||
/// Convert a general event to a scroll data event
|
|
||||||
fn convert_scroll_data(&self, event: &PlatformEventData) -> ScrollData;
|
|
||||||
/// Convert a general event to a selection data event
|
|
||||||
fn convert_selection_data(&self, event: &PlatformEventData) -> SelectionData;
|
|
||||||
/// Convert a general event to a toggle data event
|
|
||||||
fn convert_toggle_data(&self, event: &PlatformEventData) -> ToggleData;
|
|
||||||
/// Convert a general event to a touch data event
|
|
||||||
fn convert_touch_data(&self, event: &PlatformEventData) -> TouchData;
|
|
||||||
/// Convert a general event to a transition data event
|
|
||||||
fn convert_transition_data(&self, event: &PlatformEventData) -> TransitionData;
|
|
||||||
/// Convert a general event to a visible data event
|
|
||||||
fn convert_visible_data(&self, event: &PlatformEventData) -> VisibleData;
|
|
||||||
/// Convert a general event to a wheel data event
|
|
||||||
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 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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ResizeData {
|
|
||||||
fn from(val: &PlatformEventData) -> Self {
|
|
||||||
with_event_converter(|c| c.convert_resize_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 VisibleData {
|
|
||||||
fn from(val: &PlatformEventData) -> Self {
|
|
||||||
with_event_converter(|c| c.convert_visible_data(val))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&PlatformEventData> for WheelData {
|
|
||||||
fn from(val: &PlatformEventData) -> Self {
|
|
||||||
with_event_converter(|c| c.convert_wheel_data(val))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod animation;
|
mod animation;
|
||||||
mod cancel;
|
mod cancel;
|
||||||
@@ -312,6 +139,7 @@ pub use composition::*;
|
|||||||
pub use drag::*;
|
pub use drag::*;
|
||||||
pub use focus::*;
|
pub use focus::*;
|
||||||
pub use form::*;
|
pub use form::*;
|
||||||
|
pub use generated::*;
|
||||||
pub use image::*;
|
pub use image::*;
|
||||||
pub use keyboard::*;
|
pub use keyboard::*;
|
||||||
pub use media::*;
|
pub use media::*;
|
||||||
|
|||||||
@@ -213,72 +213,7 @@ use crate::geometry::{PixelsRect, PixelsSize, PixelsVector2D};
|
|||||||
|
|
||||||
pub type MountedEvent = Event<MountedData>;
|
pub type MountedEvent = Event<MountedData>;
|
||||||
|
|
||||||
impl_event! [
|
pub use super::onmounted as onmount;
|
||||||
MountedData;
|
|
||||||
|
|
||||||
#[doc(alias = "ref")]
|
|
||||||
#[doc(alias = "createRef")]
|
|
||||||
#[doc(alias = "useRef")]
|
|
||||||
/// The onmounted event is fired when the element is first added to the DOM. This event gives you a [`MountedData`] object and lets you interact with the raw DOM element.
|
|
||||||
///
|
|
||||||
/// This event is fired once per element. If you need to access the element multiple times, you can store the [`MountedData`] object in a [`use_signal`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_signal.html) hook and use it as needed.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust, no_run
|
|
||||||
/// # use dioxus::prelude::*;
|
|
||||||
/// fn App() -> Element {
|
|
||||||
/// let mut header_element = use_signal(|| None);
|
|
||||||
///
|
|
||||||
/// rsx! {
|
|
||||||
/// div {
|
|
||||||
/// h1 {
|
|
||||||
/// // The onmounted event will run the first time the h1 element is mounted
|
|
||||||
/// onmounted: move |element| header_element.set(Some(element.data())),
|
|
||||||
/// "Scroll to top example"
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// for i in 0..100 {
|
|
||||||
/// div { "Item {i}" }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// button {
|
|
||||||
/// // When you click the button, if the header element has been mounted, we scroll to that element
|
|
||||||
/// onclick: move |_| async move {
|
|
||||||
/// if let Some(header) = header_element.cloned() {
|
|
||||||
/// let _ = header.scroll_to(ScrollBehavior::Smooth).await;
|
|
||||||
/// }
|
|
||||||
/// },
|
|
||||||
/// "Scroll to top"
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The `MountedData` struct contains cross platform APIs that work on the desktop, mobile, liveview and web platforms. For the web platform, you can also downcast the `MountedData` event to the `web-sys::Element` type for more web specific APIs:
|
|
||||||
///
|
|
||||||
/// ```rust, ignore
|
|
||||||
/// use dioxus::prelude::*;
|
|
||||||
/// use dioxus_web::WebEventExt; // provides [`as_web_event()`] method
|
|
||||||
///
|
|
||||||
/// fn App() -> Element {
|
|
||||||
/// rsx! {
|
|
||||||
/// div {
|
|
||||||
/// id: "some-id",
|
|
||||||
/// onmounted: move |element| {
|
|
||||||
/// // You can use the web_event trait to downcast the element to a web specific event. For the mounted event, this will be a web_sys::Element
|
|
||||||
/// let web_sys_element = element.as_web_event();
|
|
||||||
/// assert_eq!(web_sys_element.id(), "some-id");
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
onmounted
|
|
||||||
];
|
|
||||||
|
|
||||||
pub use onmounted as onmount;
|
|
||||||
|
|
||||||
/// The MountedResult type for the MountedData
|
/// The MountedResult type for the MountedData
|
||||||
pub type MountedResult<T> = Result<T, MountedError>;
|
pub type MountedResult<T> = Result<T, MountedError>;
|
||||||
|
|||||||
@@ -44,66 +44,6 @@ pub trait HasMouseData: PointerInteraction {
|
|||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
MouseData;
|
|
||||||
|
|
||||||
/// Execute a callback when a button is clicked.
|
|
||||||
///
|
|
||||||
/// ## Description
|
|
||||||
///
|
|
||||||
/// An element receives a click event when a pointing device button (such as a mouse's primary mouse button)
|
|
||||||
/// is both pressed and released while the pointer is located inside the element.
|
|
||||||
///
|
|
||||||
/// - Bubbles: Yes
|
|
||||||
/// - Cancelable: Yes
|
|
||||||
/// - Interface(InteData): [`MouseEvent`]
|
|
||||||
///
|
|
||||||
/// If the button is pressed on one element and the pointer is moved outside the element before the button
|
|
||||||
/// is released, the event is fired on the most specific ancestor element that contained both elements.
|
|
||||||
/// `click` fires after both the `mousedown` and `mouseup` events have fired, in that order.
|
|
||||||
///
|
|
||||||
/// ## Example
|
|
||||||
/// ```rust, ignore
|
|
||||||
/// rsx!( button { onclick: move |_| tracing::info!("Clicked!"), "click me" } )
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// ## Reference
|
|
||||||
/// - <https://www.w3schools.com/tags/ev_onclick.asp>
|
|
||||||
/// - <https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event>
|
|
||||||
onclick
|
|
||||||
|
|
||||||
/// oncontextmenu
|
|
||||||
oncontextmenu
|
|
||||||
|
|
||||||
#[deprecated(since = "0.5.0", note = "use ondoubleclick instead")]
|
|
||||||
ondblclick
|
|
||||||
|
|
||||||
ondoubleclick: "ondblclick"
|
|
||||||
|
|
||||||
/// onmousedown
|
|
||||||
onmousedown
|
|
||||||
|
|
||||||
/// onmouseenter
|
|
||||||
onmouseenter
|
|
||||||
|
|
||||||
/// onmouseleave
|
|
||||||
onmouseleave
|
|
||||||
|
|
||||||
/// onmousemove
|
|
||||||
onmousemove
|
|
||||||
|
|
||||||
/// onmouseout
|
|
||||||
onmouseout
|
|
||||||
|
|
||||||
/// onmouseover
|
|
||||||
///
|
|
||||||
/// Triggered when the users's mouse hovers over an element.
|
|
||||||
onmouseover
|
|
||||||
|
|
||||||
/// onmouseup
|
|
||||||
onmouseup
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MouseData {
|
impl MouseData {
|
||||||
/// Create a new instance of MouseData
|
/// Create a new instance of MouseData
|
||||||
pub fn new(inner: impl HasMouseData + 'static) -> Self {
|
pub fn new(inner: impl HasMouseData + 'static) -> Self {
|
||||||
|
|||||||
@@ -105,42 +105,6 @@ pub trait HasPointerData: PointerInteraction {
|
|||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event![
|
|
||||||
PointerData;
|
|
||||||
/// pointerdown
|
|
||||||
onpointerdown
|
|
||||||
|
|
||||||
/// pointermove
|
|
||||||
onpointermove
|
|
||||||
|
|
||||||
/// pointerup
|
|
||||||
onpointerup
|
|
||||||
|
|
||||||
/// pointercancel
|
|
||||||
onpointercancel
|
|
||||||
|
|
||||||
/// gotpointercapture
|
|
||||||
ongotpointercapture
|
|
||||||
|
|
||||||
/// lostpointercapture
|
|
||||||
onlostpointercapture
|
|
||||||
|
|
||||||
/// pointerenter
|
|
||||||
onpointerenter
|
|
||||||
|
|
||||||
/// pointerleave
|
|
||||||
onpointerleave
|
|
||||||
|
|
||||||
/// pointerover
|
|
||||||
onpointerover
|
|
||||||
|
|
||||||
/// pointerout
|
|
||||||
onpointerout
|
|
||||||
|
|
||||||
/// auxclick
|
|
||||||
onauxclick
|
|
||||||
];
|
|
||||||
|
|
||||||
impl PointerData {
|
impl PointerData {
|
||||||
/// Gets the unique identifier of the pointer causing the event.
|
/// Gets the unique identifier of the pointer causing the event.
|
||||||
pub fn pointer_id(&self) -> i32 {
|
pub fn pointer_id(&self) -> i32 {
|
||||||
|
|||||||
@@ -132,13 +132,6 @@ use crate::geometry::PixelsSize;
|
|||||||
|
|
||||||
pub type ResizeEvent = Event<ResizeData>;
|
pub type ResizeEvent = Event<ResizeData>;
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
ResizeData;
|
|
||||||
|
|
||||||
/// onresize
|
|
||||||
onresize
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The ResizeResult type for the ResizeData
|
/// The ResizeResult type for the ResizeData
|
||||||
pub type ResizeResult<T> = Result<T, ResizeError>;
|
pub type ResizeResult<T> = Result<T, ResizeError>;
|
||||||
|
|
||||||
|
|||||||
@@ -171,13 +171,3 @@ pub trait HasScrollData: std::any::Any {
|
|||||||
/// Get the viewport height
|
/// Get the viewport height
|
||||||
fn client_height(&self) -> i32;
|
fn client_height(&self) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
ScrollData;
|
|
||||||
|
|
||||||
/// onscroll
|
|
||||||
onscroll
|
|
||||||
|
|
||||||
/// onscrollend
|
|
||||||
onscrollend
|
|
||||||
}
|
|
||||||
@@ -79,16 +79,3 @@ pub trait HasSelectionData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! [
|
|
||||||
SelectionData;
|
|
||||||
|
|
||||||
/// select
|
|
||||||
onselect
|
|
||||||
|
|
||||||
/// selectstart
|
|
||||||
onselectstart
|
|
||||||
|
|
||||||
/// selectionchange
|
|
||||||
onselectionchange
|
|
||||||
];
|
|
||||||
@@ -79,13 +79,3 @@ pub trait HasToggleData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
ToggleData;
|
|
||||||
|
|
||||||
/// ontoggle
|
|
||||||
ontoggle
|
|
||||||
|
|
||||||
/// onbeforetoggle
|
|
||||||
onbeforetoggle
|
|
||||||
}
|
|
||||||
@@ -351,18 +351,3 @@ impl InteractionLocation for SerializedTouchPoint {
|
|||||||
PagePoint::new(self.page_x, self.page_y)
|
PagePoint::new(self.page_x, self.page_y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
TouchData;
|
|
||||||
/// touchstart
|
|
||||||
ontouchstart
|
|
||||||
|
|
||||||
/// touchmove
|
|
||||||
ontouchmove
|
|
||||||
|
|
||||||
/// touchend
|
|
||||||
ontouchend
|
|
||||||
|
|
||||||
/// touchcancel
|
|
||||||
ontouchcancel
|
|
||||||
}
|
|
||||||
@@ -108,10 +108,3 @@ pub trait HasTransitionData: std::any::Any {
|
|||||||
/// return self as Any
|
/// return self as Any
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
TransitionData;
|
|
||||||
|
|
||||||
/// transitionend
|
|
||||||
ontransitionend
|
|
||||||
}
|
|
||||||
@@ -266,13 +266,6 @@ use crate::geometry::PixelsRect;
|
|||||||
|
|
||||||
pub type VisibleEvent = Event<VisibleData>;
|
pub type VisibleEvent = Event<VisibleData>;
|
||||||
|
|
||||||
impl_event! {
|
|
||||||
VisibleData;
|
|
||||||
|
|
||||||
/// onvisible
|
|
||||||
onvisible
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The VisibleResult type for the VisibleData
|
/// The VisibleResult type for the VisibleData
|
||||||
pub type VisibleResult<T> = Result<T, VisibleError>;
|
pub type VisibleResult<T> = Result<T, VisibleError>;
|
||||||
|
|
||||||
|
|||||||
@@ -223,13 +223,6 @@ impl<'de> serde::Deserialize<'de> for WheelData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_event![
|
|
||||||
WheelData;
|
|
||||||
|
|
||||||
/// Called when the mouse wheel is rotated over an element.
|
|
||||||
onwheel
|
|
||||||
];
|
|
||||||
|
|
||||||
pub trait HasWheelData: HasMouseData + std::any::Any {
|
pub trait HasWheelData: HasMouseData + std::any::Any {
|
||||||
/// The amount of wheel movement
|
/// The amount of wheel movement
|
||||||
fn delta(&self) -> WheelDelta;
|
fn delta(&self) -> WheelDelta;
|
||||||
|
|||||||
@@ -53,97 +53,12 @@ impl<'de> Deserialize<'de> for HtmlEvent {
|
|||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
fn deserialize_raw(name: &str, data: &serde_json::Value) -> Result<EventData, serde_json::Error> {
|
fn deserialize_raw(name: &str, data: &serde_json::Value) -> Result<EventData, serde_json::Error> {
|
||||||
use EventData::*;
|
match deserialize_raw_event(name, data)? {
|
||||||
|
Some(result) => Ok(result),
|
||||||
// a little macro-esque thing to make the code below more readable
|
None => Err(serde::de::Error::custom(format!(
|
||||||
#[inline]
|
"Unknown event type: {name}"
|
||||||
fn de<'de, F>(f: &'de serde_json::Value) -> Result<F, serde_json::Error>
|
))),
|
||||||
where
|
|
||||||
F: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
F::deserialize(f)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = match name {
|
|
||||||
// Cancel
|
|
||||||
"cancel" => Cancel(de(data)?),
|
|
||||||
|
|
||||||
// Mouse
|
|
||||||
"click" | "contextmenu" | "dblclick" | "doubleclick" | "mousedown" | "mouseenter"
|
|
||||||
| "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => Mouse(de(data)?),
|
|
||||||
|
|
||||||
// Clipboard
|
|
||||||
"copy" | "cut" | "paste" => Clipboard(de(data)?),
|
|
||||||
|
|
||||||
// Composition
|
|
||||||
"compositionend" | "compositionstart" | "compositionupdate" => Composition(de(data)?),
|
|
||||||
|
|
||||||
// Keyboard
|
|
||||||
"keydown" | "keypress" | "keyup" => Keyboard(de(data)?),
|
|
||||||
|
|
||||||
// Focus
|
|
||||||
"blur" | "focus" | "focusin" | "focusout" => Focus(de(data)?),
|
|
||||||
|
|
||||||
// Form
|
|
||||||
"change" | "input" | "invalid" | "reset" | "submit" => Form(de(data)?),
|
|
||||||
|
|
||||||
// Drag
|
|
||||||
"drag" | "dragend" | "dragenter" | "dragexit" | "dragleave" | "dragover" | "dragstart"
|
|
||||||
| "drop" => Drag(de(data)?),
|
|
||||||
|
|
||||||
// Pointer
|
|
||||||
"pointerlockchange" | "pointerlockerror" | "pointerdown" | "pointermove" | "pointerup"
|
|
||||||
| "pointerover" | "pointerout" | "pointerenter" | "pointerleave" | "gotpointercapture"
|
|
||||||
| "lostpointercapture" | "auxclick" => Pointer(de(data)?),
|
|
||||||
|
|
||||||
// Selection
|
|
||||||
"selectstart" | "selectionchange" | "select" => Selection(de(data)?),
|
|
||||||
|
|
||||||
// Touch
|
|
||||||
"touchcancel" | "touchend" | "touchmove" | "touchstart" => Touch(de(data)?),
|
|
||||||
|
|
||||||
// Resize
|
|
||||||
"resize" => Resize(de(data)?),
|
|
||||||
|
|
||||||
// Scroll
|
|
||||||
"scroll" | "scrollend" => Scroll(de(data)?),
|
|
||||||
|
|
||||||
// Visible
|
|
||||||
"visible" => Visible(de(data)?),
|
|
||||||
|
|
||||||
// Wheel
|
|
||||||
"wheel" => Wheel(de(data)?),
|
|
||||||
|
|
||||||
// Media
|
|
||||||
"abort" | "canplay" | "canplaythrough" | "durationchange" | "emptied" | "encrypted"
|
|
||||||
| "ended" | "interruptbegin" | "interruptend" | "loadeddata" | "loadedmetadata"
|
|
||||||
| "loadstart" | "pause" | "play" | "playing" | "progress" | "ratechange" | "seeked"
|
|
||||||
| "seeking" | "stalled" | "suspend" | "timeupdate" | "volumechange" | "waiting"
|
|
||||||
| "loadend" | "timeout" => Media(de(data)?),
|
|
||||||
|
|
||||||
// Animation
|
|
||||||
"animationstart" | "animationend" | "animationiteration" => Animation(de(data)?),
|
|
||||||
|
|
||||||
// Transition
|
|
||||||
"transitionend" => Transition(de(data)?),
|
|
||||||
|
|
||||||
// Toggle
|
|
||||||
"toggle" => Toggle(de(data)?),
|
|
||||||
|
|
||||||
"load" | "error" => Image(de(data)?),
|
|
||||||
|
|
||||||
// Mounted
|
|
||||||
"mounted" => Mounted,
|
|
||||||
|
|
||||||
// OtherData => "abort" | "afterprint" | "beforeprint" | "beforeunload" | "hashchange" | "languagechange" | "message" | "offline" | "online" | "pagehide" | "pageshow" | "popstate" | "rejectionhandled" | "storage" | "unhandledrejection" | "unload" | "userproximity" | "vrdisplayactivate" | "vrdisplayblur" | "vrdisplayconnect" | "vrdisplaydeactivate" | "vrdisplaydisconnect" | "vrdisplayfocus" | "vrdisplaypointerrestricted" | "vrdisplaypointerunrestricted" | "vrdisplaypresentchange";
|
|
||||||
other => {
|
|
||||||
return Err(serde::de::Error::custom(format!(
|
|
||||||
"Unknown event type: {other}"
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
|
|||||||
+11
-1
@@ -15,7 +15,9 @@ use rustc_hash::FxHashMap;
|
|||||||
use wasm_bindgen::{closure::Closure, JsCast};
|
use wasm_bindgen::{closure::Closure, JsCast};
|
||||||
use web_sys::{Document, Event, Node};
|
use web_sys::{Document, Event, Node};
|
||||||
|
|
||||||
use crate::{load_document, virtual_event_from_websys_event, Config, WebEventConverter};
|
use crate::{
|
||||||
|
event_type_matches, load_document, virtual_event_from_websys_event, Config, WebEventConverter,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct WebsysDom {
|
pub struct WebsysDom {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -94,6 +96,14 @@ impl WebsysDom {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Some browser features (e.g. datalist autocomplete) dispatch
|
||||||
|
// a plain Event with a typed name like "keydown" that isn't
|
||||||
|
// actually a KeyboardEvent. Drop events whose JS type doesn't
|
||||||
|
// match what the converters will unchecked-cast to.
|
||||||
|
if !event_type_matches(name.as_str(), web_sys_event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let data = virtual_event_from_websys_event(web_sys_event.clone(), target);
|
let data = virtual_event_from_websys_event(web_sys_event.clone(), target);
|
||||||
|
|
||||||
let event = dioxus_core::Event::new(Rc::new(data) as Rc<dyn Any>, bubbles);
|
let event = dioxus_core::Event::new(Rc::new(data) as Rc<dyn Any>, bubbles);
|
||||||
|
|||||||
@@ -3,12 +3,6 @@ use web_sys::Event;
|
|||||||
|
|
||||||
use super::{Synthetic, WebEventExt};
|
use super::{Synthetic, WebEventExt};
|
||||||
|
|
||||||
impl From<&Event> for Synthetic<Event> {
|
|
||||||
fn from(e: &Event) -> Self {
|
|
||||||
Synthetic::new(e.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HasClipboardData for Synthetic<Event> {
|
impl HasClipboardData for Synthetic<Event> {
|
||||||
fn as_any(&self) -> &dyn std::any::Any {
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
&self.event
|
&self.event
|
||||||
|
|||||||
+127
-199
@@ -1,6 +1,4 @@
|
|||||||
use dioxus_html::{
|
use dioxus_html::{DragData, FormData, HtmlEventConverter, ImageData, PlatformEventData};
|
||||||
DragData, FormData, HtmlEventConverter, ImageData, MountedData, PlatformEventData,
|
|
||||||
};
|
|
||||||
use form::WebFormData;
|
use form::WebFormData;
|
||||||
use load::WebImageEvent;
|
use load::WebImageEvent;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
@@ -52,170 +50,135 @@ fn downcast_event(event: &dioxus_html::PlatformEventData) -> &GenericWebSysEvent
|
|||||||
.expect("event should be a GenericWebSysEvent")
|
.expect("event should be a GenericWebSysEvent")
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HtmlEventConverter for WebEventConverter {
|
macro_rules! with_web_event_converters {
|
||||||
#[inline(always)]
|
($macro:ident) => {
|
||||||
fn convert_animation_data(
|
$macro! {
|
||||||
&self,
|
convert_animation_data(AnimationData) => web_sys::AnimationEvent;
|
||||||
event: &dioxus_html::PlatformEventData,
|
convert_cancel_data(CancelData) => web_sys::Event;
|
||||||
) -> dioxus_html::AnimationData {
|
convert_clipboard_data(ClipboardData) => web_sys::Event;
|
||||||
Synthetic::<web_sys::AnimationEvent>::from(downcast_event(event).raw.clone()).into()
|
convert_composition_data(CompositionData) => web_sys::CompositionEvent;
|
||||||
}
|
convert_drag_data(DragData) => web_sys::DragEvent => |event| {
|
||||||
|
let event = downcast_event(event);
|
||||||
#[inline(always)]
|
DragData::new(Synthetic::new(
|
||||||
fn convert_cancel_data(
|
event.raw.clone().unchecked_into::<web_sys::DragEvent>(),
|
||||||
&self,
|
))
|
||||||
event: &dioxus_html::PlatformEventData,
|
};
|
||||||
) -> dioxus_html::CancelData {
|
convert_focus_data(FocusData) => web_sys::FocusEvent;
|
||||||
Synthetic::new(downcast_event(event).raw.clone()).into()
|
convert_form_data(FormData) => web_sys::Event => |event| {
|
||||||
}
|
let event = downcast_event(event);
|
||||||
|
FormData::new(WebFormData::new(event.element.clone(), event.raw.clone()))
|
||||||
#[inline(always)]
|
};
|
||||||
fn convert_clipboard_data(
|
convert_image_data(ImageData) => web_sys::Event => |event| {
|
||||||
&self,
|
let event = downcast_event(event);
|
||||||
event: &dioxus_html::PlatformEventData,
|
ImageData::new(WebImageEvent::new(
|
||||||
) -> dioxus_html::ClipboardData {
|
event.raw.clone(),
|
||||||
Synthetic::new(downcast_event(event).raw.clone()).into()
|
event.raw.type_() == "error",
|
||||||
}
|
))
|
||||||
|
};
|
||||||
#[inline(always)]
|
convert_keyboard_data(KeyboardData) => web_sys::KeyboardEvent;
|
||||||
fn convert_composition_data(
|
convert_media_data(MediaData) => web_sys::Event;
|
||||||
&self,
|
convert_mounted_data(MountedData) => web_sys::Element => |event| {
|
||||||
event: &dioxus_html::PlatformEventData,
|
#[cfg(feature = "mounted")]
|
||||||
) -> dioxus_html::CompositionData {
|
{
|
||||||
Synthetic::<web_sys::CompositionEvent>::from(downcast_event(event).raw.clone()).into()
|
Synthetic::new(
|
||||||
}
|
event
|
||||||
|
.downcast::<web_sys::Element>()
|
||||||
#[inline(always)]
|
.expect("event should be a web_sys::Element")
|
||||||
fn convert_drag_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::DragData {
|
.clone(),
|
||||||
let event = downcast_event(event);
|
)
|
||||||
DragData::new(Synthetic::new(
|
.into()
|
||||||
event.raw.clone().unchecked_into::<web_sys::DragEvent>(),
|
}
|
||||||
))
|
#[cfg(not(feature = "mounted"))]
|
||||||
}
|
{
|
||||||
|
let _ = event;
|
||||||
#[inline(always)]
|
panic!("mounted events require the `mounted` feature on dioxus-web")
|
||||||
fn convert_focus_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::FocusData {
|
}
|
||||||
Synthetic::<web_sys::FocusEvent>::from(downcast_event(event).raw.clone()).into()
|
};
|
||||||
}
|
convert_mouse_data(MouseData) => web_sys::MouseEvent;
|
||||||
|
convert_pointer_data(PointerData) => web_sys::PointerEvent;
|
||||||
#[inline(always)]
|
convert_resize_data(ResizeData) => web_sys::ResizeObserverEntry;
|
||||||
fn convert_form_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::FormData {
|
convert_scroll_data(ScrollData) => web_sys::Event;
|
||||||
let event = downcast_event(event);
|
convert_selection_data(SelectionData) => web_sys::Event;
|
||||||
FormData::new(WebFormData::new(event.element.clone(), event.raw.clone()))
|
convert_toggle_data(ToggleData) => web_sys::Event;
|
||||||
}
|
convert_touch_data(TouchData) => web_sys::TouchEvent;
|
||||||
|
convert_transition_data(TransitionData) => web_sys::TransitionEvent;
|
||||||
#[inline(always)]
|
convert_visible_data(VisibleData) => web_sys::IntersectionObserverEntry;
|
||||||
fn convert_image_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::ImageData {
|
convert_wheel_data(WheelData) => web_sys::WheelEvent;
|
||||||
let event = downcast_event(event);
|
|
||||||
let error = event.raw.type_() == "error";
|
|
||||||
ImageData::new(WebImageEvent::new(event.raw.clone(), error))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_keyboard_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::KeyboardData {
|
|
||||||
Synthetic::<web_sys::KeyboardEvent>::from(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_media_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::MediaData {
|
|
||||||
Synthetic::new(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_mounted_data(&self, event: &dioxus_html::PlatformEventData) -> MountedData {
|
|
||||||
#[cfg(feature = "mounted")]
|
|
||||||
{
|
|
||||||
Synthetic::new(
|
|
||||||
event
|
|
||||||
.downcast::<web_sys::Element>()
|
|
||||||
.expect("event should be a web_sys::Element")
|
|
||||||
.clone(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mounted"))]
|
};
|
||||||
{
|
|
||||||
panic!("mounted events are not supported without the mounted feature on the dioxus-web crate enabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_mouse_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::MouseData {
|
|
||||||
Synthetic::<web_sys::MouseEvent>::from(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_pointer_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::PointerData {
|
|
||||||
Synthetic::<web_sys::PointerEvent>::from(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_resize_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::ResizeData {
|
|
||||||
Synthetic::<web_sys::ResizeObserverEntry>::from(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_scroll_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::ScrollData {
|
|
||||||
Synthetic::new(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_selection_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::SelectionData {
|
|
||||||
Synthetic::new(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_toggle_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::ToggleData {
|
|
||||||
Synthetic::new(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_touch_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::TouchData {
|
|
||||||
Synthetic::<web_sys::TouchEvent>::from(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_transition_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::TransitionData {
|
|
||||||
Synthetic::<web_sys::TransitionEvent>::from(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_visible_data(
|
|
||||||
&self,
|
|
||||||
event: &dioxus_html::PlatformEventData,
|
|
||||||
) -> dioxus_html::VisibleData {
|
|
||||||
Synthetic::<web_sys::IntersectionObserverEntry>::from(downcast_event(event).raw.clone())
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn convert_wheel_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::WheelData {
|
|
||||||
Synthetic::<web_sys::WheelEvent>::from(downcast_event(event).raw.clone()).into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! expand_web_event_converter {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
$converter:ident($data:ident) => $web_ty:ty $(=> |$event:ident| $body:block)?;
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
macro_rules! web_event_type_matches {
|
||||||
|
$(
|
||||||
|
($event_name:ident, $converter) => {
|
||||||
|
$event_name.is_instance_of::<$web_ty>()
|
||||||
|
};
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HtmlEventConverter for WebEventConverter {
|
||||||
|
$(
|
||||||
|
expand_web_event_converter!(@method $converter, $data, $web_ty $(, $event, $body)?);
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(@method $converter:ident, $data:ident, $web_ty:ty) => {
|
||||||
|
#[inline(always)]
|
||||||
|
fn $converter(&self, event: &PlatformEventData) -> dioxus_html::$data {
|
||||||
|
Synthetic::new(downcast_event(event).raw.clone().unchecked_into::<$web_ty>()).into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(@method $converter:ident, $data:ident, $web_ty:ty, $event:ident, $body:block) => {
|
||||||
|
#[inline(always)]
|
||||||
|
fn $converter(&self, $event: &PlatformEventData) -> dioxus_html::$data $body
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
with_web_event_converters!(expand_web_event_converter);
|
||||||
|
|
||||||
|
macro_rules! expand_web_event_changes {
|
||||||
|
(
|
||||||
|
enum Event {
|
||||||
|
$(
|
||||||
|
#[convert = $converter:ident]
|
||||||
|
#[events = [
|
||||||
|
$(
|
||||||
|
$( #[$attr:meta] )*
|
||||||
|
$name:ident => $raw:ident,
|
||||||
|
)*
|
||||||
|
]]
|
||||||
|
$(#[raw = [$($raw_only:ident),* $(,)?]])?
|
||||||
|
$group:ident($data:ident),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
pub(crate) fn event_type_matches(name: &str, event: &web_sys::Event) -> bool {
|
||||||
|
let m = match name {
|
||||||
|
$(
|
||||||
|
$( stringify!($raw) )|* $($(| stringify!($raw_only))*)? => {
|
||||||
|
web_event_type_matches!(event, $converter)
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
|
if !m {
|
||||||
|
tracing::warn!("Ignoring \"{name}\": not the expected type: {event:?}");
|
||||||
|
}
|
||||||
|
m
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dioxus_html::with_html_event_groups!(expand_web_event_changes);
|
||||||
|
|
||||||
/// A extension trait for web-sys events that provides a way to get the event as a web-sys event.
|
/// A extension trait for web-sys events that provides a way to get the event as a web-sys event.
|
||||||
pub trait WebEventExt {
|
pub trait WebEventExt {
|
||||||
/// The web specific event type
|
/// The web specific event type
|
||||||
@@ -262,38 +225,3 @@ pub(crate) fn load_document() -> Document {
|
|||||||
.document()
|
.document()
|
||||||
.expect("should have access to the Document")
|
.expect("should have access to the Document")
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! uncheck_convert {
|
|
||||||
($t:ty) => {
|
|
||||||
impl From<Event> for Synthetic<$t> {
|
|
||||||
#[inline]
|
|
||||||
fn from(e: Event) -> Self {
|
|
||||||
let e: $t = e.unchecked_into();
|
|
||||||
Self::new(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Event> for Synthetic<$t> {
|
|
||||||
#[inline]
|
|
||||||
fn from(e: &Event) -> Self {
|
|
||||||
let e: &$t = e.unchecked_ref();
|
|
||||||
Self::new(e.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($($t:ty),+ $(,)?) => {
|
|
||||||
$(uncheck_convert!($t);)+
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
uncheck_convert![
|
|
||||||
web_sys::CompositionEvent,
|
|
||||||
web_sys::KeyboardEvent,
|
|
||||||
web_sys::TouchEvent,
|
|
||||||
web_sys::PointerEvent,
|
|
||||||
web_sys::WheelEvent,
|
|
||||||
web_sys::AnimationEvent,
|
|
||||||
web_sys::TransitionEvent,
|
|
||||||
web_sys::MouseEvent,
|
|
||||||
web_sys::FocusEvent,
|
|
||||||
];
|
|
||||||
Reference in new issue
Block a user