allow many attributes to be attached to one element

This commit is contained in:
Evan Almloff committed 2023-09-20 16:02:04 -05:00
1 parent dc446b5e5b
commit fc8c25280a
12 files changed
+289 -96

No files matched your search

+68 -8
View File
@@ -60,7 +60,7 @@ pub struct VNode<'a> {
pub dynamic_nodes: &'a [DynamicNode<'a>],
/// The dynamic parts of the template
pub dynamic_attrs: &'a [Attribute<'a>],
pub dynamic_attrs: &'a [MountedAttribute<'a>],
}
impl<'a> VNode<'a> {
@@ -414,6 +414,44 @@ pub enum TemplateAttribute<'a> {
},
}
#[derive(Debug)]
pub struct MountedAttribute<'a> {
pub(crate) ty: AttributeType<'a>,
/// The element in the DOM that this attribute belongs to
pub(crate) mounted_element: Cell<ElementId>,
}
impl<'a> From<Attribute<'a>> for MountedAttribute<'a> {
fn from(attr: Attribute<'a>) -> Self {
Self {
ty: AttributeType::Single(attr),
mounted_element: Default::default(),
}
}
}
impl<'a> From<&'a [Attribute<'a>]> for MountedAttribute<'a> {
fn from(attr: &'a [Attribute<'a>]) -> Self {
Self {
ty: AttributeType::Many(attr),
mounted_element: Default::default(),
}
}
}
impl<'a> MountedAttribute<'a> {
/// Get the type of this attribute
pub fn attribute_type(&self) -> &AttributeType<'a> {
&self.ty
}
/// Get the element that this attribute is mounted to
pub fn mounted_element(&self) -> ElementId {
self.mounted_element.get()
}
}
/// An attribute on a DOM node, such as `id="my-thing"` or `href="https://example.com"`
#[derive(Debug)]
pub struct Attribute<'a> {
@@ -430,9 +468,6 @@ pub struct Attribute<'a> {
/// An indication of we should always try and set the attribute. Used in controlled components to ensure changes are propagated
pub volatile: bool,
/// The element in the DOM that this attribute belongs to
pub(crate) mounted_element: Cell<ElementId>,
}
impl<'a> Attribute<'a> {
@@ -448,13 +483,38 @@ impl<'a> Attribute<'a> {
value,
namespace,
volatile,
mounted_element: Cell::new(ElementId::default()),
}
}
}
#[derive(Debug)]
pub enum AttributeType<'a> {
Single(Attribute<'a>),
/// Many different attributes sorted by name
Many(&'a [Attribute<'a>]),
}
impl<'a> AttributeType<'a> {
/// Call the given function on each attribute
pub fn for_each<'b, F>(&'b self, mut f: F)
where
F: FnMut(&'b Attribute<'a>),
{
match self {
Self::Single(attr) => f(attr),
Self::Many(attrs) => attrs.iter().for_each(f),
}
}
/// Get the element that this attribute is mounted to
pub fn mounted_element(&self) -> ElementId {
self.mounted_element.get()
/// Try to call the given function on each attribute
pub fn try_for_each<'b, F, E>(&'b self, mut f: F) -> Result<(), E>
where
F: FnMut(&'b Attribute<'a>) -> Result<(), E>,
{
match self {
Self::Single(attr) => f(attr),
Self::Many(attrs) => attrs.iter().try_for_each(f),
}
}
}