Merge branch 'master' into jk/breaking-merged

This commit is contained in:
Jonathan Kelley committed 2024-01-11 16:04:36 -08:00
commit 2ae3241cc0
211 files changed
+21135 -3770

No files matched your search

+127 -18
View File
@@ -1,12 +1,16 @@
use std::{any::Any, collections::HashMap};
use dioxus_html::{
FileEngine, FormData, HasFormData, HasImageData, HtmlEventConverter, ImageData, MountedData,
PlatformEventData, ScrollData,
point_interaction::{
InteractionElementOffset, InteractionLocation, ModifiersInteraction, PointerInteraction,
},
prelude::FormValue,
DragData, FileEngine, FormData, HasDragData, HasFileData, HasFormData, HasImageData,
HasMouseData, HtmlEventConverter, ImageData, MountedData, PlatformEventData, ScrollData,
};
use js_sys::Array;
use wasm_bindgen::{prelude::wasm_bindgen, JsCast};
use web_sys::{Document, Element, Event};
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
use web_sys::{Document, Element, Event, MouseEvent};
pub(crate) struct WebEventConverter;
@@ -44,7 +48,11 @@ impl HtmlEventConverter for WebEventConverter {
#[inline(always)]
fn convert_drag_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::DragData {
downcast_event(event).raw.clone().into()
let event = downcast_event(event);
DragData::new(WebDragData::new(
event.element.clone(),
event.raw.clone().unchecked_into(),
))
}
#[inline(always)]
@@ -180,8 +188,10 @@ impl WebEventExt<web_sys::CompositionEvent> for dioxus_html::CompositionData {
impl WebEventExt<web_sys::MouseEvent> for dioxus_html::DragData {
fn web_event(&self) -> &web_sys::MouseEvent {
self.downcast::<web_sys::MouseEvent>()
&self
.downcast::<WebDragData>()
.expect("event should be a WebMouseEvent")
.raw
}
}
@@ -378,7 +388,7 @@ impl HasFormData for WebFormData {
.expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener")
}
fn values(&self) -> HashMap<String, Vec<String>> {
fn values(&self) -> HashMap<String, FormValue> {
let mut values = std::collections::HashMap::new();
// try to fill in form values
@@ -388,10 +398,12 @@ impl HasFormData for WebFormData {
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>() {
let item_values =
let item_values: Vec<String> =
item_values.iter().filter_map(|v| v.as_string()).collect();
values.insert(name, item_values);
values.insert(name, FormValue::VecText(item_values));
} else if let Ok(item_value) = array.get(1).dyn_into::<JsValue>() {
values.insert(name, FormValue::Text(item_value.as_string().unwrap()));
}
}
}
@@ -401,6 +413,12 @@ impl HasFormData for WebFormData {
values
}
fn as_any(&self) -> &dyn Any {
&self.raw as &dyn Any
}
}
impl HasFileData for WebFormData {
fn files(&self) -> Option<std::sync::Arc<dyn FileEngine>> {
#[cfg(not(feature = "file_engine"))]
let files = None;
@@ -419,24 +437,115 @@ impl HasFormData for WebFormData {
files
}
}
fn as_any(&self) -> &dyn Any {
&self.raw as &dyn Any
struct WebDragData {
element: Element,
raw: MouseEvent,
}
impl WebDragData {
fn new(element: Element, raw: MouseEvent) -> Self {
Self { element, 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 {
fn files(&self) -> Option<std::sync::Arc<dyn FileEngine>> {
#[cfg(not(feature = "file_engine"))]
let files = None;
#[cfg(feature = "file_engine")]
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 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);
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));
for (let name of formData.keys()) {
const fieldType = target.elements[name].type;
switch (fieldType) {
case "select-multiple":
contents.values[name] = formData.getAll(name);
break;
// add cases for fieldTypes that can hold multiple values here
default:
contents.values[name] = formData.get(name);
break;
}
return values;
}
return values;
}
"#)]
extern "C" {
fn get_form_data(form: &web_sys::HtmlFormElement) -> js_sys::Map;
+9 -5
View File
@@ -1,4 +1,5 @@
use crate::dom::WebsysDom;
use dioxus_core::AttributeValue;
use dioxus_core::{DynamicNode, ElementId, ScopeState, TemplateNode, VNode, VirtualDom};
#[derive(Debug)]
@@ -81,12 +82,15 @@ impl WebsysDom {
if let dioxus_core::TemplateAttribute::Dynamic { id } = attr {
let attribute = &vnode.dynamic_attrs[*id];
let id = attribute.mounted_element();
mounted_id = Some(id);
if let dioxus_core::AttributeValue::Listener(_) = attribute.value {
if attribute.name == "onmounted" {
to_mount.push(id);
attribute.attribute_type().for_each(|attribute| {
let value = &attribute.value;
mounted_id = Some(id);
if let AttributeValue::Listener(_) = value {
if attribute.name == "onmounted" {
to_mount.push(id);
}
}
}
});
}
}
if let Some(id) = mounted_id {