瀏覽代碼

create onmounted event

Evan Almloff 2 年之前
父節點
當前提交
920fcf728c
共有 4 個文件被更改,包括 139 次插入3 次删除
  1. 5 0
      packages/html/Cargo.toml
  2. 3 0
      packages/html/src/events.rs
  3. 85 0
      packages/html/src/events/mounted.rs
  4. 46 3
      packages/html/src/web_sys_bind/events.rs

+ 5 - 0
packages/html/Cargo.toml

@@ -39,6 +39,11 @@ features = [
     "FocusEvent",
     "CompositionEvent",
     "ClipboardEvent",
+    "Element",
+    "DomRect",
+    "ScrollIntoViewOptions",
+    "ScrollLogicalPosition",
+    "ScrollBehavior",
 ]
 
 [dev-dependencies]

+ 3 - 0
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,
     }
 }

+ 85 - 0
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<Rect<f64, f64>> {
+        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<dyn RenderedElementBacking>,
+}
+
+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<Rect<f64, f64>> {
+        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<MountedData>;
+
+impl_event! [
+    MountedData;
+
+    /// mounted
+    onmounted
+];

+ 46 - 3
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<euclid::Rect<f64, f64>> {
+        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::<web_sys::HtmlElement>().and_then(|e| {
+            if focus {
+                e.focus().ok()
+            } else {
+                e.blur().ok()
+            }
+        })
+    }
+}