diff --git a/crates/xilem_html/src/element/elements.rs b/crates/xilem_html/src/element/elements.rs
index cdd3826f9..a02aa007d 100644
--- a/crates/xilem_html/src/element/elements.rs
+++ b/crates/xilem_html/src/element/elements.rs
@@ -15,7 +15,6 @@ use wasm_bindgen::JsCast;
use crate::{event::EventMsg, Event, Pod};
use wasm_bindgen::UnwrapThrowExt;
-use web_sys::console::log_1 as console_log;
macro_rules! debug_warn {
($($arg:tt)*) => {{
@@ -24,13 +23,6 @@ macro_rules! debug_warn {
}}
}
-macro_rules! debug_log {
- ($($arg:tt)*) => {{
- #[cfg(debug_assertions)]
- web_sys::console::log_1(&format!($($arg)*).into());
- }}
-}
-
use super::{remove_attribute, set_attribute};
macro_rules! elements {
() => {};
@@ -263,17 +255,8 @@ elements!(
(Template, template, web_sys::HtmlTemplateElement),
);
-// TODO think about using serialized values instead of Box for smaller compilation size (but likely worse performance)
-// TODO consider enum for common attribute types and Box as fallback for more exotic cases
-// TODO consider Vec<(&'static str, Box)> instead of BTreeMap (should likely be faster than BTreeMap for very few attributes (~ < 10-20 attributes))
-type Attrs = BTreeMap<&'static str, Box>;
-
-type CowStr = Cow<'static, str>;
-
pub struct VecMap(Vec<(K, V)>);
-type AttrsNew = VecMap;
-
impl Default for VecMap {
fn default() -> Self {
Self(Vec::new())
@@ -339,12 +322,6 @@ impl VecMap {
}
}
-impl AttrsNew {
- fn insert_untyped(&mut self, name: impl Into, value: impl Into) {
- self.insert(name.into(), AttributeValue::String(value.into()));
- }
-}
-
pub fn diff_tree_maps<'a, K: Ord, V: PartialEq>(
prev: &'a BTreeMap,
next: &'a BTreeMap,
@@ -404,12 +381,15 @@ pub enum Diff {
Change(K, V),
}
+type CowStr = Cow<'static, str>;
+
// TODO in the future it's likely there's an element that doesn't implement PartialEq,
// but for now it's simpler for diffing, maybe also use some kind of serialization in that case
#[derive(PartialEq, Debug)]
pub enum AttributeValue {
U32(u32),
I32(i32),
+ F32(f32),
F64(f64),
String(CowStr),
// for classes mostly
@@ -431,6 +411,7 @@ impl AttributeValue {
match self {
AttributeValue::U32(n) => n.to_string().into(),
AttributeValue::I32(n) => n.to_string().into(),
+ AttributeValue::F32(n) => n.to_string().into(),
AttributeValue::F64(n) => n.to_string().into(),
AttributeValue::String(s) => s.clone(),
// currently just concatenates strings with spaces in between,
@@ -451,27 +432,58 @@ impl AttributeValue {
}
}
-const UNTYPED_ATTRS: &str = "____untyped_attrs____";
-
-/// returns all attribute keys including untyped attributes
-fn attr_keys(attrs: &Attrs) -> impl Iterator- {
- attrs.keys().copied().filter(|a| *a != UNTYPED_ATTRS).chain(
- attrs
- .get(UNTYPED_ATTRS)
- .map(|untyped_attrs| {
- untyped_attrs
- .downcast_ref::>()
- .unwrap()
- .keys()
- .map(|k| k.as_str())
- })
- .into_iter()
- .flatten(),
- )
+impl From for AttributeValue {
+ fn from(value: u32) -> Self {
+ AttributeValue::U32(value)
+ }
}
-pub trait Node {
- fn node_name(&self) -> &str;
+impl From for AttributeValue {
+ fn from(value: i32) -> Self {
+ AttributeValue::I32(value)
+ }
+}
+
+impl From for AttributeValue {
+ fn from(value: f32) -> Self {
+ AttributeValue::F32(value)
+ }
+}
+
+impl From for AttributeValue {
+ fn from(value: f64) -> Self {
+ AttributeValue::F64(value)
+ }
+}
+
+impl From for AttributeValue {
+ fn from(value: String) -> Self {
+ AttributeValue::String(value.into())
+ }
+}
+
+impl From for AttributeValue {
+ fn from(value: CowStr) -> Self {
+ AttributeValue::String(value)
+ }
+}
+
+impl From<&'static str> for AttributeValue {
+ fn from(value: &'static str) -> Self {
+ AttributeValue::String(value.into())
+ }
+}
+
+type Attrs = VecMap;
+
+impl Attrs {
+ fn insert_untyped(&mut self, name: impl Into, value: impl Into) {
+ self.insert(name.into(), AttributeValue::String(value.into()));
+ }
+
+ fn insert_attr(&mut self, name: impl Into, value: impl Into) {
+ self.insert(name.into(), value.into());
+ }
}
pub trait EventHandler {
@@ -533,289 +545,62 @@ impl A> EventHandler for F {
}
}
-// TODO might be useful, but is currently not needed
-// // type erased event handler
-// trait AnyEventHandler {
-// fn as_any(&self) -> &dyn std::any::Any;
-
-// fn dyn_build(&self, cx: &mut crate::context::Cx) -> (xilem_core::Id, Box);
-
-// // TODO should id be mutable like in View::rebuild?
-// fn dyn_rebuild(
-// &self,
-// cx: &mut crate::context::Cx,
-// prev: &dyn AnyEventHandler,
-// id: &mut xilem_core::Id,
-// state: &mut Box,
-// ) -> crate::ChangeFlags;
-
-// fn dyn_message(
-// &self,
-// id_path: &[xilem_core::Id],
-// state: &mut dyn Any,
-// message: Box,
-// app_state: &mut T,
-// ) -> xilem_core::MessageResult;
-// }
-
-// impl AnyEventHandler for EH
-// where
-// EH: EventHandler + 'static,
-// EH::State: 'static,
-// {
-// fn as_any(&self) -> &dyn std::any::Any {
-// self
-// }
-
-// fn dyn_build(&self, cx: &mut crate::context::Cx) -> (xilem_core::Id, Box) {
-// let (id, state) = self.build(cx);
-// (id, Box::new(state))
-// }
-
-// fn dyn_rebuild(
-// &self,
-// cx: &mut crate::context::Cx,
-// prev: &dyn AnyEventHandler,
-// id: &mut xilem_core::Id,
-// state: &mut Box,
-// ) -> crate::ChangeFlags {
-// if let Some(prev) = prev.as_any().downcast_ref() {
-// if let Some(state) = state.downcast_mut() {
-// self.rebuild(cx, prev, id, state)
-// } else {
-// // TODO warning
-// // eprintln!("downcast of state failed in dyn_rebuild");
-// crate::ChangeFlags::default()
-// }
-// } else {
-// let (new_id, new_state) = self.build(cx);
-// *id = new_id;
-// *state = Box::new(new_state);
-// crate::ChangeFlags::tree_structure()
-// }
-// }
-
-// fn dyn_message(
-// &self,
-// id_path: &[xilem_core::Id],
-// state: &mut dyn std::any::Any,
-// message: Box,
-// app_state: &mut T,
-// ) -> xilem_core::MessageResult {
-// if let Some(state) = state.downcast_mut() {
-// self.message(id_path, state, message, app_state)
-// } else {
-// // TODO warning
-// // panic!("downcast error in dyn_event");
-// xilem_core::MessageResult::Stale(message)
-// }
-// }
-// }
-
-pub trait ElementNew: Node + crate::view::View {
- // TODO rename to class (currently conflicts with `ViewExt`)
- fn classes(self, class: C) -> Self;
- // TODO rename to class (currently conflicts with `ViewExt`)
- fn add_classes(&mut self, class: C);
- // TODO should this be in its own trait? (it doesn't have much to do with the DOM Node interface)
- fn raw_attrs(&self) -> &AttrsNew;
- // TODO should this be in Node?
- fn attr, V: Into>(self, key: K, value: V) -> Self;
- fn set_attr, V: Into>(&mut self, key: K, value: V);
-
- fn onclick(self, handler: EH) -> Self
- where
- T: 'static,
- A: 'static,
- EH: EventHandler> + 'static;
-
- fn onscroll(self, handler: EH) -> Self
- where
- T: 'static,
- A: 'static,
- EH: EventHandler> + 'static;
-}
-
-type EventListenersState = Vec<(xilem_core::Id, Box)>;
-
-pub struct MyElementState {
- children_states: ViewSeqState,
- children_elements: Vec,
- event_listener_state: EventListenersState,
- scratch: Vec,
-}
-
-// TODO not sure how much it helps reducing the code size,
-// but the two attributes could be extracted into its own type, and the actual element type is just a single tuple struct wrapping this type,
-pub struct MyHtmlElement {
- pub(crate) attrs: AttrsNew,
- // TODO maybe there's a better dynamic trait for this (event handlers can contain different event types...)
- // event_listeners: VecMap