dioxus_web/events/
mounted.rs1use dioxus_html::{
2 geometry::euclid::{Point2D, Size2D},
3 MountedData,
4};
5use wasm_bindgen::JsCast;
6
7use super::{Synthetic, WebEventExt};
8
9impl dioxus_html::RenderedElementBacking for Synthetic<web_sys::Element> {
10 fn get_scroll_offset(
11 &self,
12 ) -> std::pin::Pin<
13 Box<
14 dyn std::future::Future<
15 Output = dioxus_html::MountedResult<dioxus_html::geometry::PixelsVector2D>,
16 >,
17 >,
18 > {
19 let left = self.event.scroll_left();
20 let top = self.event.scroll_top();
21 let result = Ok(dioxus_html::geometry::PixelsVector2D::new(
22 left as f64,
23 top as f64,
24 ));
25 Box::pin(async { result })
26 }
27
28 fn get_scroll_size(
29 &self,
30 ) -> std::pin::Pin<
31 Box<
32 dyn std::future::Future<
33 Output = dioxus_html::MountedResult<dioxus_html::geometry::PixelsSize>,
34 >,
35 >,
36 > {
37 let width = self.event.scroll_width();
38 let height = self.event.scroll_height();
39 let result = Ok(dioxus_html::geometry::PixelsSize::new(
40 width as f64,
41 height as f64,
42 ));
43 Box::pin(async { result })
44 }
45
46 fn get_client_rect(
47 &self,
48 ) -> std::pin::Pin<
49 Box<
50 dyn std::future::Future<
51 Output = dioxus_html::MountedResult<dioxus_html::geometry::PixelsRect>,
52 >,
53 >,
54 > {
55 let rect = self.event.get_bounding_client_rect();
56 let result = Ok(dioxus_html::geometry::PixelsRect::new(
57 Point2D::new(rect.left(), rect.top()),
58 Size2D::new(rect.width(), rect.height()),
59 ));
60 Box::pin(async { result })
61 }
62
63 fn as_any(&self) -> &dyn std::any::Any {
64 &self.event
65 }
66
67 fn scroll_to(
68 &self,
69 input_options: dioxus_html::ScrollToOptions,
70 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = dioxus_html::MountedResult<()>>>> {
71 let options = web_sys::ScrollIntoViewOptions::new();
72 options.set_behavior(match input_options.behavior {
73 dioxus_html::ScrollBehavior::Instant => web_sys::ScrollBehavior::Instant,
74 dioxus_html::ScrollBehavior::Smooth => web_sys::ScrollBehavior::Smooth,
75 });
76 options.set_block(match input_options.vertical {
77 dioxus_html::ScrollLogicalPosition::Start => web_sys::ScrollLogicalPosition::Start,
78 dioxus_html::ScrollLogicalPosition::Center => web_sys::ScrollLogicalPosition::Center,
79 dioxus_html::ScrollLogicalPosition::End => web_sys::ScrollLogicalPosition::End,
80 dioxus_html::ScrollLogicalPosition::Nearest => web_sys::ScrollLogicalPosition::Nearest,
81 });
82 options.set_inline(match input_options.horizontal {
83 dioxus_html::ScrollLogicalPosition::Start => web_sys::ScrollLogicalPosition::Start,
84 dioxus_html::ScrollLogicalPosition::Center => web_sys::ScrollLogicalPosition::Center,
85 dioxus_html::ScrollLogicalPosition::End => web_sys::ScrollLogicalPosition::End,
86 dioxus_html::ScrollLogicalPosition::Nearest => web_sys::ScrollLogicalPosition::Nearest,
87 });
88 self.event
89 .scroll_into_view_with_scroll_into_view_options(&options);
90
91 Box::pin(async { Ok(()) })
92 }
93
94 fn scroll(
95 &self,
96 coordinates: dioxus_html::geometry::PixelsVector2D,
97 behavior: dioxus_html::ScrollBehavior,
98 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = dioxus_html::MountedResult<()>>>> {
99 let options = web_sys::ScrollToOptions::new();
100 options.set_top(coordinates.y);
101 options.set_left(coordinates.x);
102 match behavior {
103 dioxus_html::ScrollBehavior::Instant => {
104 options.set_behavior(web_sys::ScrollBehavior::Instant);
105 }
106 dioxus_html::ScrollBehavior::Smooth => {
107 options.set_behavior(web_sys::ScrollBehavior::Smooth);
108 }
109 }
110 self.event.scroll_with_scroll_to_options(&options);
111
112 Box::pin(async { Ok(()) })
113 }
114
115 fn set_focus(
116 &self,
117 focus: bool,
118 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = dioxus_html::MountedResult<()>>>> {
119 #[derive(Debug)]
120 struct FocusError(wasm_bindgen::JsValue);
121
122 impl std::fmt::Display for FocusError {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 write!(f, "failed to focus element {:?}", self.0)
125 }
126 }
127
128 impl std::error::Error for FocusError {}
129
130 let result = self
131 .event
132 .dyn_ref::<web_sys::HtmlElement>()
133 .ok_or_else(|| {
134 dioxus_html::MountedError::OperationFailed(Box::new(FocusError(
135 self.event.clone().into(),
136 )))
137 })
138 .and_then(|e| {
139 (if focus { e.focus() } else { e.blur() }).map_err(|err| {
140 dioxus_html::MountedError::OperationFailed(Box::new(FocusError(err)))
141 })
142 });
143 Box::pin(async { result })
144 }
145}
146
147impl WebEventExt for MountedData {
148 type WebEvent = web_sys::Element;
149
150 #[inline(always)]
151 fn try_as_web_event(&self) -> Option<web_sys::Element> {
152 self.downcast::<web_sys::Element>().cloned()
153 }
154}