Remove native and web features from dioxus-html (#3006)
* remove native and web features from dioxus-html * Fix downcasting web events * Fix desktop with tokio disabled
This commit is contained in:
1 parent
677e0e7f4f
commit
cda8bb24f1
54 files changed
+1768
-1512
No files matched your search
@@ -0,0 +1,32 @@
|
||||
use dioxus_html::HasAnimationData;
|
||||
use web_sys::AnimationEvent;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasAnimationData for Synthetic<AnimationEvent> {
|
||||
fn animation_name(&self) -> String {
|
||||
self.event.animation_name()
|
||||
}
|
||||
|
||||
fn pseudo_element(&self) -> String {
|
||||
self.event.pseudo_element()
|
||||
}
|
||||
|
||||
fn elapsed_time(&self) -> f32 {
|
||||
self.event.elapsed_time()
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::AnimationData {
|
||||
type WebEvent = web_sys::AnimationEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::AnimationEvent> {
|
||||
self.downcast::<Synthetic<web_sys::AnimationEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
use dioxus_html::HasClipboardData;
|
||||
use web_sys::Event;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl From<&Event> for Synthetic<Event> {
|
||||
fn from(e: &Event) -> Self {
|
||||
Synthetic::new(e.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasClipboardData for Synthetic<Event> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::ClipboardData {
|
||||
type WebEvent = web_sys::Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::Event>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use dioxus_html::HasCompositionData;
|
||||
use web_sys::CompositionEvent;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasCompositionData for Synthetic<CompositionEvent> {
|
||||
fn data(&self) -> std::string::String {
|
||||
self.event.data().unwrap_or_default()
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::CompositionData {
|
||||
type WebEvent = web_sys::CompositionEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::CompositionEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
use dioxus_html::{
|
||||
prelude::{
|
||||
InteractionElementOffset, InteractionLocation, ModifiersInteraction, PointerInteraction,
|
||||
},
|
||||
HasDragData, HasFileData, HasMouseData,
|
||||
};
|
||||
use web_sys::MouseEvent;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
pub(crate) struct WebDragData {
|
||||
raw: Synthetic<MouseEvent>,
|
||||
}
|
||||
|
||||
impl WebDragData {
|
||||
pub fn new(raw: MouseEvent) -> Self {
|
||||
Self {
|
||||
raw: Synthetic::new(raw),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasDragData for WebDragData {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
&self.raw as &dyn std::any::Any
|
||||
}
|
||||
}
|
||||
|
||||
impl HasMouseData for WebDragData {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
&self.raw as &dyn std::any::Any
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerInteraction for WebDragData {
|
||||
fn trigger_button(&self) -> Option<dioxus_html::input_data::MouseButton> {
|
||||
self.raw.trigger_button()
|
||||
}
|
||||
|
||||
fn held_buttons(&self) -> dioxus_html::input_data::MouseButtonSet {
|
||||
self.raw.held_buttons()
|
||||
}
|
||||
}
|
||||
|
||||
impl ModifiersInteraction for WebDragData {
|
||||
fn modifiers(&self) -> dioxus_html::prelude::Modifiers {
|
||||
self.raw.modifiers()
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionElementOffset for WebDragData {
|
||||
fn coordinates(&self) -> dioxus_html::geometry::Coordinates {
|
||||
self.raw.coordinates()
|
||||
}
|
||||
|
||||
fn element_coordinates(&self) -> dioxus_html::geometry::ElementPoint {
|
||||
self.raw.element_coordinates()
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionLocation for WebDragData {
|
||||
fn client_coordinates(&self) -> dioxus_html::geometry::ClientPoint {
|
||||
self.raw.client_coordinates()
|
||||
}
|
||||
|
||||
fn screen_coordinates(&self) -> dioxus_html::geometry::ScreenPoint {
|
||||
self.raw.screen_coordinates()
|
||||
}
|
||||
|
||||
fn page_coordinates(&self) -> dioxus_html::geometry::PagePoint {
|
||||
self.raw.page_coordinates()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasFileData for WebDragData {
|
||||
#[cfg(feature = "file_engine")]
|
||||
fn files(&self) -> Option<std::sync::Arc<dyn dioxus_html::FileEngine>> {
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
let files = self
|
||||
.raw
|
||||
.event
|
||||
.dyn_ref::<web_sys::DragEvent>()
|
||||
.and_then(|drag_event| {
|
||||
drag_event.data_transfer().and_then(|dt| {
|
||||
dt.files().and_then(|files| {
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
crate::file_engine::WebFileEngine::new(files).map(|f| {
|
||||
std::sync::Arc::new(f) as std::sync::Arc<dyn dioxus_html::FileEngine>
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
files
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::DragData {
|
||||
type WebEvent = web_sys::MouseEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::MouseEvent> {
|
||||
self.downcast::<WebDragData>()
|
||||
.map(|data| &data.raw.event)
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use dioxus_html::HasFileData;
|
||||
|
||||
use super::Synthetic;
|
||||
|
||||
impl HasFileData for Synthetic<web_sys::Event> {
|
||||
#[cfg(feature = "file_engine")]
|
||||
fn files(&self) -> Option<std::sync::Arc<dyn dioxus_html::FileEngine>> {
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
let files = self
|
||||
.event
|
||||
.dyn_ref()
|
||||
.and_then(|input: &web_sys::HtmlInputElement| {
|
||||
input.files().and_then(|files| {
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
crate::file_engine::WebFileEngine::new(files).map(|f| {
|
||||
std::sync::Arc::new(f) as std::sync::Arc<dyn dioxus_html::FileEngine>
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
files
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use dioxus_html::HasFocusData;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasFocusData for Synthetic<web_sys::FocusEvent> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::FocusData {
|
||||
type WebEvent = web_sys::FocusEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::FocusEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
use std::{any::Any, collections::HashMap};
|
||||
|
||||
use dioxus_html::{FormValue, HasFileData, HasFormData};
|
||||
use js_sys::Array;
|
||||
use wasm_bindgen::JsValue;
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsCast};
|
||||
use web_sys::{Element, Event};
|
||||
|
||||
use super::WebEventExt;
|
||||
|
||||
pub(crate) struct WebFormData {
|
||||
element: Element,
|
||||
raw: Event,
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::FormData {
|
||||
type WebEvent = Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<WebFormData>().map(|e| e.raw.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl WebFormData {
|
||||
pub fn new(element: Element, raw: Event) -> Self {
|
||||
Self { element, raw }
|
||||
}
|
||||
}
|
||||
|
||||
impl HasFormData for WebFormData {
|
||||
fn value(&self) -> String {
|
||||
let target = &self.element;
|
||||
target
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlInputElement| {
|
||||
// todo: special case more input types
|
||||
match input.type_().as_str() {
|
||||
"checkbox" => {
|
||||
match input.checked() {
|
||||
true => "true".to_string(),
|
||||
false => "false".to_string(),
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
input.value()
|
||||
}
|
||||
}
|
||||
})
|
||||
.or_else(|| {
|
||||
target
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlTextAreaElement| input.value())
|
||||
})
|
||||
// select elements are NOT input events - because - why woudn't they be??
|
||||
.or_else(|| {
|
||||
target
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlSelectElement| input.value())
|
||||
})
|
||||
.or_else(|| {
|
||||
target
|
||||
.dyn_ref::<web_sys::HtmlElement>()
|
||||
.unwrap()
|
||||
.text_content()
|
||||
})
|
||||
.expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener")
|
||||
}
|
||||
|
||||
fn values(&self) -> HashMap<String, FormValue> {
|
||||
let mut values = HashMap::new();
|
||||
|
||||
fn insert_value(map: &mut HashMap<String, FormValue>, key: String, new_value: String) {
|
||||
map.entry(key.clone()).or_default().0.push(new_value);
|
||||
}
|
||||
|
||||
// try to fill in form values
|
||||
if let Some(form) = self.element.dyn_ref::<web_sys::HtmlFormElement>() {
|
||||
let form_data = get_form_data(form);
|
||||
for value in form_data.entries().into_iter().flatten() {
|
||||
if let Ok(array) = value.dyn_into::<Array>() {
|
||||
if let Some(name) = array.get(0).as_string() {
|
||||
if let Ok(item_values) = array.get(1).dyn_into::<Array>() {
|
||||
item_values
|
||||
.iter()
|
||||
.filter_map(|v| v.as_string())
|
||||
.for_each(|v| insert_value(&mut values, name.clone(), v));
|
||||
} else if let Ok(item_value) = array.get(1).dyn_into::<JsValue>() {
|
||||
insert_value(&mut values, name, item_value.as_string().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(select) = self.element.dyn_ref::<web_sys::HtmlSelectElement>() {
|
||||
// try to fill in select element values
|
||||
let options = get_select_data(select);
|
||||
values.insert("options".to_string(), FormValue(options));
|
||||
}
|
||||
|
||||
values
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
&self.raw as &dyn Any
|
||||
}
|
||||
}
|
||||
|
||||
impl HasFileData for WebFormData {
|
||||
#[cfg(feature = "file_engine")]
|
||||
fn files(&self) -> Option<std::sync::Arc<dyn dioxus_html::FileEngine>> {
|
||||
let files = self
|
||||
.element
|
||||
.dyn_ref()
|
||||
.and_then(|input: &web_sys::HtmlInputElement| {
|
||||
input.files().and_then(|files| {
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
crate::file_engine::WebFileEngine::new(files).map(|f| {
|
||||
std::sync::Arc::new(f) as std::sync::Arc<dyn dioxus_html::FileEngine>
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
files
|
||||
}
|
||||
}
|
||||
|
||||
// web-sys does not expose the keys api for select data, so we need to manually bind to it
|
||||
#[wasm_bindgen(inline_js = r#"
|
||||
export function get_select_data(select) {
|
||||
let values = [];
|
||||
for (let i = 0; i < select.options.length; i++) {
|
||||
let option = select.options[i];
|
||||
if (option.selected) {
|
||||
values.push(option.value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
"#)]
|
||||
extern "C" {
|
||||
fn get_select_data(select: &web_sys::HtmlSelectElement) -> Vec<String>;
|
||||
}
|
||||
|
||||
// web-sys does not expose the keys api for form data, so we need to manually bind to it
|
||||
#[wasm_bindgen(inline_js = r#"
|
||||
export function get_form_data(form) {
|
||||
let values = new Map();
|
||||
const formData = new FormData(form);
|
||||
|
||||
for (let name of formData.keys()) {
|
||||
values.set(name, formData.getAll(name));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
"#)]
|
||||
extern "C" {
|
||||
fn get_form_data(form: &web_sys::HtmlFormElement) -> js_sys::Map;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use dioxus_html::{
|
||||
input_data::decode_key_location,
|
||||
prelude::{Code, Key, Location, Modifiers, ModifiersInteraction},
|
||||
HasKeyboardData,
|
||||
};
|
||||
use web_sys::KeyboardEvent;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasKeyboardData for Synthetic<KeyboardEvent> {
|
||||
fn key(&self) -> Key {
|
||||
Key::from_str(self.event.key().as_str()).unwrap_or(Key::Unidentified)
|
||||
}
|
||||
|
||||
fn code(&self) -> Code {
|
||||
Code::from_str(self.event.code().as_str()).unwrap_or(Code::Unidentified)
|
||||
}
|
||||
|
||||
fn location(&self) -> Location {
|
||||
decode_key_location(self.event.location() as usize)
|
||||
}
|
||||
|
||||
fn is_auto_repeating(&self) -> bool {
|
||||
self.event.repeat()
|
||||
}
|
||||
|
||||
fn is_composing(&self) -> bool {
|
||||
self.event.is_composing()
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ModifiersInteraction for Synthetic<KeyboardEvent> {
|
||||
fn modifiers(&self) -> Modifiers {
|
||||
let mut modifiers = Modifiers::empty();
|
||||
|
||||
if self.event.alt_key() {
|
||||
modifiers.insert(Modifiers::ALT);
|
||||
}
|
||||
if self.event.ctrl_key() {
|
||||
modifiers.insert(Modifiers::CONTROL);
|
||||
}
|
||||
if self.event.meta_key() {
|
||||
modifiers.insert(Modifiers::META);
|
||||
}
|
||||
if self.event.shift_key() {
|
||||
modifiers.insert(Modifiers::SHIFT);
|
||||
}
|
||||
|
||||
modifiers
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::KeyboardData {
|
||||
type WebEvent = web_sys::KeyboardEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::KeyboardEvent> {
|
||||
self.downcast::<Synthetic<web_sys::KeyboardEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
use std::any::Any;
|
||||
|
||||
use dioxus_html::HasImageData;
|
||||
use web_sys::Event;
|
||||
|
||||
use super::WebEventExt;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct WebImageEvent {
|
||||
raw: Event,
|
||||
error: bool,
|
||||
}
|
||||
|
||||
impl WebImageEvent {
|
||||
pub fn new(raw: Event, error: bool) -> Self {
|
||||
Self { raw, error }
|
||||
}
|
||||
}
|
||||
|
||||
impl HasImageData for WebImageEvent {
|
||||
fn load_error(&self) -> bool {
|
||||
self.error
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
&self.raw as &dyn Any
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::ImageData {
|
||||
type WebEvent = Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Event> {
|
||||
self.downcast::<WebImageEvent>().map(|e| e.raw.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use dioxus_html::HasMediaData;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasMediaData for Synthetic<web_sys::Event> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::MediaData {
|
||||
type WebEvent = web_sys::Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::Event>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
use dioxus_html::{
|
||||
DragData, FormData, HtmlEventConverter, ImageData, MountedData, PlatformEventData,
|
||||
};
|
||||
use drag::WebDragData;
|
||||
use form::WebFormData;
|
||||
use load::WebImageEvent;
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::{Document, Element, Event};
|
||||
|
||||
mod animation;
|
||||
mod clipboard;
|
||||
mod composition;
|
||||
mod drag;
|
||||
mod file;
|
||||
mod focus;
|
||||
mod form;
|
||||
mod keyboard;
|
||||
mod load;
|
||||
mod media;
|
||||
#[cfg(feature = "mounted")]
|
||||
mod mounted;
|
||||
mod mouse;
|
||||
mod pointer;
|
||||
mod resize;
|
||||
mod selection;
|
||||
mod toggle;
|
||||
mod touch;
|
||||
mod transition;
|
||||
mod wheel;
|
||||
|
||||
/// A wrapper for the websys event that allows us to give it the impls from dioxus-html
|
||||
pub(crate) struct Synthetic<T: 'static> {
|
||||
/// The inner web sys event that the synthetic event wraps
|
||||
pub event: T,
|
||||
}
|
||||
|
||||
impl<T: 'static> Synthetic<T> {
|
||||
/// Create a new synthetic event from a web sys event
|
||||
pub fn new(event: T) -> Self {
|
||||
Self { event }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct WebEventConverter;
|
||||
|
||||
#[inline(always)]
|
||||
fn downcast_event(event: &dioxus_html::PlatformEventData) -> &GenericWebSysEvent {
|
||||
event
|
||||
.downcast::<GenericWebSysEvent>()
|
||||
.expect("event should be a GenericWebSysEvent")
|
||||
}
|
||||
|
||||
impl HtmlEventConverter for WebEventConverter {
|
||||
#[inline(always)]
|
||||
fn convert_animation_data(
|
||||
&self,
|
||||
event: &dioxus_html::PlatformEventData,
|
||||
) -> dioxus_html::AnimationData {
|
||||
Synthetic::<web_sys::AnimationEvent>::from(downcast_event(event).raw.clone()).into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn convert_clipboard_data(
|
||||
&self,
|
||||
event: &dioxus_html::PlatformEventData,
|
||||
) -> dioxus_html::ClipboardData {
|
||||
Synthetic::new(downcast_event(event).raw.clone()).into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn convert_composition_data(
|
||||
&self,
|
||||
event: &dioxus_html::PlatformEventData,
|
||||
) -> dioxus_html::CompositionData {
|
||||
Synthetic::<web_sys::CompositionEvent>::from(downcast_event(event).raw.clone()).into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn convert_drag_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::DragData {
|
||||
let event = downcast_event(event);
|
||||
DragData::new(WebDragData::new(event.raw.clone().unchecked_into()))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn convert_focus_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::FocusData {
|
||||
Synthetic::<web_sys::FocusEvent>::from(downcast_event(event).raw.clone()).into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn convert_form_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::FormData {
|
||||
let event = downcast_event(event);
|
||||
FormData::new(WebFormData::new(event.element.clone(), event.raw.clone()))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn convert_image_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::ImageData {
|
||||
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_wheel_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::WheelData {
|
||||
Synthetic::<web_sys::WheelEvent>::from(downcast_event(event).raw.clone()).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// A extension trait for web-sys events that provides a way to get the event as a web-sys event.
|
||||
pub trait WebEventExt {
|
||||
/// The web specific event type
|
||||
type WebEvent;
|
||||
|
||||
/// Try to downcast this event as a `web-sys` event.
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent>;
|
||||
|
||||
/// Downcast this event as a `web-sys` event.
|
||||
#[inline(always)]
|
||||
fn as_web_event(&self) -> Self::WebEvent
|
||||
where
|
||||
Self::WebEvent: 'static,
|
||||
{
|
||||
self.try_as_web_event().unwrap_or_else(|| {
|
||||
panic!(
|
||||
"Error downcasting to `web-sys`, event should be a {}.",
|
||||
std::any::type_name::<Self::WebEvent>()
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct GenericWebSysEvent {
|
||||
raw: Event,
|
||||
element: Element,
|
||||
}
|
||||
|
||||
// todo: some of these events are being casted to the wrong event type.
|
||||
// We need tests that simulate clicks/etc and make sure every event type works.
|
||||
pub(crate) fn virtual_event_from_websys_event(
|
||||
event: web_sys::Event,
|
||||
target: Element,
|
||||
) -> PlatformEventData {
|
||||
PlatformEventData::new(Box::new(GenericWebSysEvent {
|
||||
raw: event,
|
||||
element: target,
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn load_document() -> Document {
|
||||
web_sys::window()
|
||||
.expect("should have access to the Window")
|
||||
.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,
|
||||
];
|
||||
@@ -0,0 +1,126 @@
|
||||
use dioxus_html::{
|
||||
geometry::euclid::{Point2D, Size2D},
|
||||
MountedData,
|
||||
};
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl dioxus_html::RenderedElementBacking for Synthetic<web_sys::Element> {
|
||||
fn get_scroll_offset(
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = dioxus_html::MountedResult<dioxus_html::geometry::PixelsVector2D>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
let left = self.event.scroll_left();
|
||||
let top = self.event.scroll_top();
|
||||
let result = Ok(dioxus_html::geometry::PixelsVector2D::new(
|
||||
left as f64,
|
||||
top as f64,
|
||||
));
|
||||
Box::pin(async { result })
|
||||
}
|
||||
|
||||
fn get_scroll_size(
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = dioxus_html::MountedResult<dioxus_html::geometry::PixelsSize>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
let width = self.event.scroll_width();
|
||||
let height = self.event.scroll_height();
|
||||
let result = Ok(dioxus_html::geometry::PixelsSize::new(
|
||||
width as f64,
|
||||
height as f64,
|
||||
));
|
||||
Box::pin(async { result })
|
||||
}
|
||||
|
||||
fn get_client_rect(
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = dioxus_html::MountedResult<dioxus_html::geometry::PixelsRect>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
let rect = self.event.get_bounding_client_rect();
|
||||
let result = Ok(dioxus_html::geometry::PixelsRect::new(
|
||||
Point2D::new(rect.left(), rect.top()),
|
||||
Size2D::new(rect.width(), rect.height()),
|
||||
));
|
||||
Box::pin(async { result })
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn scroll_to(
|
||||
&self,
|
||||
behavior: dioxus_html::ScrollBehavior,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = dioxus_html::MountedResult<()>>>> {
|
||||
let options = web_sys::ScrollIntoViewOptions::new();
|
||||
match behavior {
|
||||
dioxus_html::ScrollBehavior::Instant => {
|
||||
options.set_behavior(web_sys::ScrollBehavior::Instant);
|
||||
}
|
||||
dioxus_html::ScrollBehavior::Smooth => {
|
||||
options.set_behavior(web_sys::ScrollBehavior::Smooth);
|
||||
}
|
||||
}
|
||||
self.event
|
||||
.scroll_into_view_with_scroll_into_view_options(&options);
|
||||
|
||||
Box::pin(async { Ok(()) })
|
||||
}
|
||||
|
||||
fn set_focus(
|
||||
&self,
|
||||
focus: bool,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = dioxus_html::MountedResult<()>>>> {
|
||||
#[derive(Debug)]
|
||||
struct FocusError(wasm_bindgen::JsValue);
|
||||
|
||||
impl std::fmt::Display for FocusError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "failed to focus element {:?}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for FocusError {}
|
||||
|
||||
let result = self
|
||||
.event
|
||||
.dyn_ref::<web_sys::HtmlElement>()
|
||||
.ok_or_else(|| {
|
||||
dioxus_html::MountedError::OperationFailed(Box::new(FocusError(
|
||||
self.event.clone().into(),
|
||||
)))
|
||||
})
|
||||
.and_then(|e| {
|
||||
(if focus { e.focus() } else { e.blur() }).map_err(|err| {
|
||||
dioxus_html::MountedError::OperationFailed(Box::new(FocusError(err)))
|
||||
})
|
||||
});
|
||||
Box::pin(async { result })
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for MountedData {
|
||||
type WebEvent = web_sys::Element;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::Element> {
|
||||
self.downcast::<Synthetic<web_sys::Element>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
use dioxus_html::{
|
||||
geometry::{ClientPoint, ElementPoint, PagePoint, ScreenPoint},
|
||||
input_data::{decode_mouse_button_set, MouseButton},
|
||||
prelude::{
|
||||
InteractionElementOffset, InteractionLocation, Modifiers, ModifiersInteraction,
|
||||
PointerInteraction,
|
||||
},
|
||||
HasDragData, HasFileData, HasMouseData,
|
||||
};
|
||||
use web_sys::MouseEvent;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl InteractionLocation for Synthetic<MouseEvent> {
|
||||
fn client_coordinates(&self) -> ClientPoint {
|
||||
ClientPoint::new(self.event.client_x().into(), self.event.client_y().into())
|
||||
}
|
||||
|
||||
fn page_coordinates(&self) -> PagePoint {
|
||||
PagePoint::new(self.event.page_x().into(), self.event.page_y().into())
|
||||
}
|
||||
|
||||
fn screen_coordinates(&self) -> ScreenPoint {
|
||||
ScreenPoint::new(self.event.screen_x().into(), self.event.screen_y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionElementOffset for Synthetic<MouseEvent> {
|
||||
fn element_coordinates(&self) -> ElementPoint {
|
||||
ElementPoint::new(self.event.offset_x().into(), self.event.offset_y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ModifiersInteraction for Synthetic<MouseEvent> {
|
||||
fn modifiers(&self) -> Modifiers {
|
||||
let mut modifiers = Modifiers::empty();
|
||||
|
||||
if self.event.alt_key() {
|
||||
modifiers.insert(Modifiers::ALT);
|
||||
}
|
||||
if self.event.ctrl_key() {
|
||||
modifiers.insert(Modifiers::CONTROL);
|
||||
}
|
||||
if self.event.meta_key() {
|
||||
modifiers.insert(Modifiers::META);
|
||||
}
|
||||
if self.event.shift_key() {
|
||||
modifiers.insert(Modifiers::SHIFT);
|
||||
}
|
||||
|
||||
modifiers
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerInteraction for Synthetic<MouseEvent> {
|
||||
fn held_buttons(&self) -> dioxus_html::input_data::MouseButtonSet {
|
||||
decode_mouse_button_set(self.event.buttons())
|
||||
}
|
||||
|
||||
fn trigger_button(&self) -> Option<MouseButton> {
|
||||
Some(MouseButton::from_web_code(self.event.button()))
|
||||
}
|
||||
}
|
||||
|
||||
impl HasMouseData for Synthetic<MouseEvent> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl HasFileData for Synthetic<MouseEvent> {}
|
||||
|
||||
impl HasDragData for Synthetic<MouseEvent> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::MouseData {
|
||||
type WebEvent = web_sys::MouseEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::MouseEvent> {
|
||||
self.downcast::<Synthetic<web_sys::MouseEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
use dioxus_html::{
|
||||
geometry::{ClientPoint, ElementPoint, PagePoint, ScreenPoint},
|
||||
input_data::{decode_mouse_button_set, MouseButton},
|
||||
prelude::{
|
||||
InteractionElementOffset, InteractionLocation, Modifiers, ModifiersInteraction,
|
||||
PointerInteraction,
|
||||
},
|
||||
HasPointerData,
|
||||
};
|
||||
use web_sys::PointerEvent;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasPointerData for Synthetic<PointerEvent> {
|
||||
fn pointer_id(&self) -> i32 {
|
||||
self.event.pointer_id()
|
||||
}
|
||||
|
||||
fn width(&self) -> i32 {
|
||||
self.event.width()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
self.event.height()
|
||||
}
|
||||
|
||||
fn pressure(&self) -> f32 {
|
||||
self.event.pressure()
|
||||
}
|
||||
|
||||
fn tangential_pressure(&self) -> f32 {
|
||||
self.event.tangential_pressure()
|
||||
}
|
||||
|
||||
fn tilt_x(&self) -> i32 {
|
||||
self.event.tilt_x()
|
||||
}
|
||||
|
||||
fn tilt_y(&self) -> i32 {
|
||||
self.event.tilt_y()
|
||||
}
|
||||
|
||||
fn twist(&self) -> i32 {
|
||||
self.event.twist()
|
||||
}
|
||||
|
||||
fn pointer_type(&self) -> String {
|
||||
self.event.pointer_type()
|
||||
}
|
||||
|
||||
fn is_primary(&self) -> bool {
|
||||
self.event.is_primary()
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionLocation for Synthetic<PointerEvent> {
|
||||
fn client_coordinates(&self) -> ClientPoint {
|
||||
ClientPoint::new(self.event.client_x().into(), self.event.client_y().into())
|
||||
}
|
||||
|
||||
fn screen_coordinates(&self) -> ScreenPoint {
|
||||
ScreenPoint::new(self.event.screen_x().into(), self.event.screen_y().into())
|
||||
}
|
||||
|
||||
fn page_coordinates(&self) -> PagePoint {
|
||||
PagePoint::new(self.event.page_x().into(), self.event.page_y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionElementOffset for Synthetic<PointerEvent> {
|
||||
fn element_coordinates(&self) -> ElementPoint {
|
||||
ElementPoint::new(self.event.offset_x().into(), self.event.offset_y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ModifiersInteraction for Synthetic<PointerEvent> {
|
||||
fn modifiers(&self) -> Modifiers {
|
||||
let mut modifiers = Modifiers::empty();
|
||||
|
||||
if self.event.alt_key() {
|
||||
modifiers.insert(Modifiers::ALT);
|
||||
}
|
||||
if self.event.ctrl_key() {
|
||||
modifiers.insert(Modifiers::CONTROL);
|
||||
}
|
||||
if self.event.meta_key() {
|
||||
modifiers.insert(Modifiers::META);
|
||||
}
|
||||
if self.event.shift_key() {
|
||||
modifiers.insert(Modifiers::SHIFT);
|
||||
}
|
||||
|
||||
modifiers
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerInteraction for Synthetic<PointerEvent> {
|
||||
fn held_buttons(&self) -> dioxus_html::input_data::MouseButtonSet {
|
||||
decode_mouse_button_set(self.event.buttons())
|
||||
}
|
||||
|
||||
fn trigger_button(&self) -> Option<MouseButton> {
|
||||
Some(MouseButton::from_web_code(self.event.button()))
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::PointerData {
|
||||
type WebEvent = web_sys::PointerEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::PointerEvent> {
|
||||
self.downcast::<Synthetic<web_sys::PointerEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
use dioxus_html::{geometry::PixelsSize, HasResizeData, ResizeResult};
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::{CustomEvent, Event, ResizeObserverEntry};
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl From<Event> for Synthetic<ResizeObserverEntry> {
|
||||
#[inline]
|
||||
fn from(e: Event) -> Self {
|
||||
<Synthetic<ResizeObserverEntry> as From<&Event>>::from(&e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Event> for Synthetic<ResizeObserverEntry> {
|
||||
#[inline]
|
||||
fn from(e: &Event) -> Self {
|
||||
let e: &CustomEvent = e.unchecked_ref();
|
||||
let value = e.detail();
|
||||
Self::new(value.unchecked_into::<ResizeObserverEntry>())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasResizeData for Synthetic<ResizeObserverEntry> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn get_border_box_size(&self) -> ResizeResult<PixelsSize> {
|
||||
extract_first_size(self.event.border_box_size())
|
||||
}
|
||||
|
||||
fn get_content_box_size(&self) -> ResizeResult<PixelsSize> {
|
||||
extract_first_size(self.event.content_box_size())
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::ResizeData {
|
||||
type WebEvent = web_sys::ResizeObserverEntry;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::ResizeObserverEntry> {
|
||||
self.downcast::<Synthetic<web_sys::ResizeObserverEntry>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_first_size(resize_observer_output: js_sys::Array) -> ResizeResult<PixelsSize> {
|
||||
let first = resize_observer_output.get(0);
|
||||
let size = first.unchecked_into::<web_sys::ResizeObserverSize>();
|
||||
|
||||
// inline_size matches the width of the element if its writing-mode is horizontal, the height otherwise
|
||||
let inline_size = size.inline_size();
|
||||
// block_size matches the height of the element if its writing-mode is horizontal, the width otherwise
|
||||
let block_size = size.block_size();
|
||||
|
||||
Ok(PixelsSize::new(inline_size, block_size))
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use dioxus_html::HasSelectionData;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasSelectionData for Synthetic<web_sys::Event> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::SelectionData {
|
||||
type WebEvent = web_sys::Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::Event>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use dioxus_html::HasToggleData;
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasToggleData for Synthetic<web_sys::Event> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::ToggleData {
|
||||
type WebEvent = web_sys::Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::Event>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
use dioxus_html::{
|
||||
geometry::{ClientPoint, PagePoint, ScreenPoint},
|
||||
prelude::{InteractionLocation, Modifiers, ModifiersInteraction},
|
||||
HasTouchPointData, TouchPoint,
|
||||
};
|
||||
use web_sys::{Touch, TouchEvent};
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl ModifiersInteraction for Synthetic<TouchEvent> {
|
||||
fn modifiers(&self) -> Modifiers {
|
||||
let mut modifiers = Modifiers::empty();
|
||||
|
||||
if self.event.alt_key() {
|
||||
modifiers.insert(Modifiers::ALT);
|
||||
}
|
||||
if self.event.ctrl_key() {
|
||||
modifiers.insert(Modifiers::CONTROL);
|
||||
}
|
||||
if self.event.meta_key() {
|
||||
modifiers.insert(Modifiers::META);
|
||||
}
|
||||
if self.event.shift_key() {
|
||||
modifiers.insert(Modifiers::SHIFT);
|
||||
}
|
||||
|
||||
modifiers
|
||||
}
|
||||
}
|
||||
|
||||
impl dioxus_html::events::HasTouchData for Synthetic<TouchEvent> {
|
||||
fn touches(&self) -> Vec<TouchPoint> {
|
||||
let touches = TouchEvent::touches(&self.event);
|
||||
let mut result = Vec::with_capacity(touches.length() as usize);
|
||||
for i in 0..touches.length() {
|
||||
let touch = touches.get(i).unwrap();
|
||||
result.push(TouchPoint::new(Synthetic::new(touch)));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn touches_changed(&self) -> Vec<TouchPoint> {
|
||||
let touches = self.event.changed_touches();
|
||||
let mut result = Vec::with_capacity(touches.length() as usize);
|
||||
for i in 0..touches.length() {
|
||||
let touch = touches.get(i).unwrap();
|
||||
result.push(TouchPoint::new(Synthetic::new(touch)));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn target_touches(&self) -> Vec<TouchPoint> {
|
||||
let touches = self.event.target_touches();
|
||||
let mut result = Vec::with_capacity(touches.length() as usize);
|
||||
for i in 0..touches.length() {
|
||||
let touch = touches.get(i).unwrap();
|
||||
result.push(TouchPoint::new(Synthetic::new(touch)));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTouchPointData for Synthetic<Touch> {
|
||||
fn identifier(&self) -> i32 {
|
||||
self.event.identifier()
|
||||
}
|
||||
|
||||
fn radius(&self) -> ScreenPoint {
|
||||
ScreenPoint::new(self.event.radius_x().into(), self.event.radius_y().into())
|
||||
}
|
||||
|
||||
fn rotation(&self) -> f64 {
|
||||
self.event.rotation_angle() as f64
|
||||
}
|
||||
|
||||
fn force(&self) -> f64 {
|
||||
self.event.force() as f64
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionLocation for Synthetic<Touch> {
|
||||
fn client_coordinates(&self) -> ClientPoint {
|
||||
ClientPoint::new(self.event.client_x().into(), self.event.client_y().into())
|
||||
}
|
||||
|
||||
fn screen_coordinates(&self) -> ScreenPoint {
|
||||
ScreenPoint::new(self.event.screen_x().into(), self.event.screen_y().into())
|
||||
}
|
||||
|
||||
fn page_coordinates(&self) -> PagePoint {
|
||||
PagePoint::new(self.event.page_x().into(), self.event.page_y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::TouchData {
|
||||
type WebEvent = web_sys::TouchEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<web_sys::TouchEvent> {
|
||||
self.downcast::<Synthetic<web_sys::TouchEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use dioxus_html::HasTransitionData;
|
||||
use web_sys::TransitionEvent;
|
||||
|
||||
use super::Synthetic;
|
||||
|
||||
impl HasTransitionData for Synthetic<TransitionEvent> {
|
||||
fn elapsed_time(&self) -> f32 {
|
||||
self.event.elapsed_time()
|
||||
}
|
||||
|
||||
fn property_name(&self) -> String {
|
||||
self.event.property_name()
|
||||
}
|
||||
|
||||
fn pseudo_element(&self) -> String {
|
||||
self.event.pseudo_element()
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
use dioxus_html::{
|
||||
geometry::{ClientPoint, ElementPoint, PagePoint, ScreenPoint},
|
||||
input_data::{decode_mouse_button_set, MouseButton},
|
||||
prelude::{
|
||||
InteractionElementOffset, InteractionLocation, Modifiers, ModifiersInteraction,
|
||||
PointerInteraction,
|
||||
},
|
||||
HasMouseData, HasScrollData, HasWheelData,
|
||||
};
|
||||
use web_sys::{Event, WheelEvent};
|
||||
|
||||
use super::{Synthetic, WebEventExt};
|
||||
|
||||
impl HasWheelData for Synthetic<WheelEvent> {
|
||||
fn delta(&self) -> dioxus_html::geometry::WheelDelta {
|
||||
dioxus_html::geometry::WheelDelta::from_web_attributes(
|
||||
self.event.delta_mode(),
|
||||
self.event.delta_x(),
|
||||
self.event.delta_y(),
|
||||
self.event.delta_z(),
|
||||
)
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl HasMouseData for Synthetic<WheelEvent> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionLocation for Synthetic<WheelEvent> {
|
||||
fn client_coordinates(&self) -> ClientPoint {
|
||||
ClientPoint::new(self.event.client_x().into(), self.event.client_y().into())
|
||||
}
|
||||
|
||||
fn screen_coordinates(&self) -> ScreenPoint {
|
||||
ScreenPoint::new(self.event.screen_x().into(), self.event.screen_y().into())
|
||||
}
|
||||
|
||||
fn page_coordinates(&self) -> PagePoint {
|
||||
PagePoint::new(self.event.page_x().into(), self.event.page_y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl InteractionElementOffset for Synthetic<WheelEvent> {
|
||||
fn element_coordinates(&self) -> ElementPoint {
|
||||
ElementPoint::new(self.event.offset_x().into(), self.event.offset_y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ModifiersInteraction for Synthetic<WheelEvent> {
|
||||
fn modifiers(&self) -> Modifiers {
|
||||
let mut modifiers = Modifiers::empty();
|
||||
|
||||
if self.event.alt_key() {
|
||||
modifiers.insert(Modifiers::ALT);
|
||||
}
|
||||
if self.event.ctrl_key() {
|
||||
modifiers.insert(Modifiers::CONTROL);
|
||||
}
|
||||
if self.event.meta_key() {
|
||||
modifiers.insert(Modifiers::META);
|
||||
}
|
||||
if self.event.shift_key() {
|
||||
modifiers.insert(Modifiers::SHIFT);
|
||||
}
|
||||
|
||||
modifiers
|
||||
}
|
||||
}
|
||||
|
||||
impl PointerInteraction for Synthetic<WheelEvent> {
|
||||
fn held_buttons(&self) -> dioxus_html::input_data::MouseButtonSet {
|
||||
decode_mouse_button_set(self.event.buttons())
|
||||
}
|
||||
|
||||
fn trigger_button(&self) -> Option<MouseButton> {
|
||||
Some(MouseButton::from_web_code(self.event.button()))
|
||||
}
|
||||
}
|
||||
|
||||
impl HasScrollData for Synthetic<Event> {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::ScrollData {
|
||||
type WebEvent = web_sys::Event;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::Event>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl WebEventExt for dioxus_html::WheelData {
|
||||
type WebEvent = web_sys::WheelEvent;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_as_web_event(&self) -> Option<Self::WebEvent> {
|
||||
self.downcast::<Synthetic<web_sys::WheelEvent>>()
|
||||
.map(|e| e.event.clone())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user