diff --git a/packages/html/Cargo.toml b/packages/html/Cargo.toml
index e60fcd8e5..513cc253a 100644
--- a/packages/html/Cargo.toml
+++ b/packages/html/Cargo.toml
@@ -39,6 +39,11 @@ features = [
"FocusEvent",
"CompositionEvent",
"ClipboardEvent",
+ "Element",
+ "DomRect",
+ "ScrollIntoViewOptions",
+ "ScrollLogicalPosition",
+ "ScrollBehavior",
]
[dev-dependencies]
diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs
index 853400c28..85a408d0b 100644
--- a/packages/html/src/events.rs
+++ b/packages/html/src/events.rs
@@ -33,6 +33,7 @@ mod form;
mod image;
mod keyboard;
mod media;
+mod mounted;
mod mouse;
mod pointer;
mod scroll;
@@ -51,6 +52,7 @@ pub use form::*;
pub use image::*;
pub use keyboard::*;
pub use media::*;
+pub use mounted::*;
pub use mouse::*;
pub use pointer::*;
pub use scroll::*;
@@ -144,6 +146,7 @@ pub fn event_bubbles(evt: &str) -> bool {
"animationiteration" => true,
"transitionend" => true,
"toggle" => true,
+ "mounted" => false,
_ => true,
}
}
diff --git a/packages/html/src/events/mounted.rs b/packages/html/src/events/mounted.rs
new file mode 100644
index 000000000..a5413bb5b
--- /dev/null
+++ b/packages/html/src/events/mounted.rs
@@ -0,0 +1,85 @@
+//! Handles quering data from the renderer
+
+use euclid::Rect;
+
+use std::{any::Any, rc::Rc};
+
+/// An Element that has been rendered and allows reading and modifying information about it.
+///
+/// Different platforms will have different implementations and different levels of support for this trait. Renderers that do not support specific features will return `None` for those queries.
+pub trait RenderedElementBacking {
+ /// Get the renderer specific element for the given id
+ fn get_raw_element(&self) -> Option<&dyn Any> {
+ None
+ }
+
+ /// Get the bounding rectangle of the element relative to the viewport (this does not include the scroll position)
+ fn get_client_rect(&self) -> Option> {
+ None
+ }
+
+ /// Scroll to make the element visible
+ fn scroll_to(&self, _behavior: ScrollBehavior) -> Option<()> {
+ None
+ }
+
+ /// Set the focus on the element
+ fn set_focus(&self, _focus: bool) -> Option<()> {
+ None
+ }
+}
+
+/// The way that scrolling should be performed
+pub enum ScrollBehavior {
+ /// Scroll to the element immediately
+ Instant,
+ /// Scroll to the element smoothly
+ Smooth,
+}
+
+/// An Element that has been rendered and allows reading and modifying information about it.
+///
+/// Different platforms will have different implementations and different levels of support for this trait. Renderers that do not support specific features will return `None` for those queries.
+pub struct MountedData {
+ inner: Rc,
+}
+
+impl MountedData {
+ /// Create a new MountedData
+ pub fn new(registry: impl RenderedElementBacking + 'static) -> Self {
+ Self {
+ inner: Rc::new(registry),
+ }
+ }
+
+ /// Get the renderer specific element for the given id
+ pub fn get_raw_element(&self) -> Option<&dyn Any> {
+ self.inner.get_raw_element()
+ }
+
+ /// Get the bounding rectangle of the element relative to the viewport (this does not include the scroll position)
+ pub fn get_client_rect(&self) -> Option> {
+ self.inner.get_client_rect()
+ }
+
+ /// Scroll to make the element visible
+ pub fn scroll_to(&self, behavior: ScrollBehavior) -> Option<()> {
+ self.inner.scroll_to(behavior)
+ }
+
+ /// Set the focus on the element
+ pub fn set_focus(&self, focus: bool) -> Option<()> {
+ self.inner.set_focus(focus)
+ }
+}
+
+use dioxus_core::Event;
+
+pub type MountedEvent = Event;
+
+impl_event! [
+ MountedData;
+
+ /// mounted
+ onmounted
+];
diff --git a/packages/html/src/web_sys_bind/events.rs b/packages/html/src/web_sys_bind/events.rs
index 196099444..01b25dfc2 100644
--- a/packages/html/src/web_sys_bind/events.rs
+++ b/packages/html/src/web_sys_bind/events.rs
@@ -4,14 +4,14 @@ use crate::events::{
};
use crate::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint};
use crate::input_data::{decode_key_location, decode_mouse_button_set, MouseButton};
-use crate::DragData;
+use crate::{DragData, MountedData, RenderedElementBacking, ScrollBehavior};
use keyboard_types::{Code, Key, Modifiers};
use std::convert::TryInto;
use std::str::FromStr;
use wasm_bindgen::JsCast;
use web_sys::{
- AnimationEvent, CompositionEvent, Event, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent,
- TransitionEvent, WheelEvent,
+ AnimationEvent, CompositionEvent, Event, KeyboardEvent, MouseEvent, PointerEvent,
+ ScrollIntoViewOptions, TouchEvent, TransitionEvent, WheelEvent,
};
macro_rules! uncheck_convert {
@@ -193,3 +193,46 @@ impl From<&TransitionEvent> for TransitionData {
}
}
}
+
+impl From<&web_sys::Element> for MountedData {
+ fn from(e: &web_sys::Element) -> Self {
+ MountedData::new(e.clone())
+ }
+}
+
+impl RenderedElementBacking for web_sys::Element {
+ fn get_client_rect(&self) -> Option> {
+ let rect = self.get_bounding_client_rect();
+ Some(euclid::Rect::new(
+ euclid::Point2D::new(rect.left(), rect.top()),
+ euclid::Size2D::new(rect.width(), rect.height()),
+ ))
+ }
+
+ fn get_raw_element(&self) -> Option<&dyn std::any::Any> {
+ Some(self)
+ }
+
+ fn scroll_to(&self, behavior: ScrollBehavior) -> Option<()> {
+ match behavior {
+ ScrollBehavior::Instant => self.scroll_into_view_with_scroll_into_view_options(
+ ScrollIntoViewOptions::new().behavior(web_sys::ScrollBehavior::Instant),
+ ),
+ ScrollBehavior::Smooth => self.scroll_into_view_with_scroll_into_view_options(
+ ScrollIntoViewOptions::new().behavior(web_sys::ScrollBehavior::Smooth),
+ ),
+ }
+
+ Some(())
+ }
+
+ fn set_focus(&self, focus: bool) -> Option<()> {
+ self.dyn_ref::().and_then(|e| {
+ if focus {
+ e.focus().ok()
+ } else {
+ e.blur().ok()
+ }
+ })
+ }
+}