use super::{
attribute::{Attribute, NextAttribute},
element::ElementType,
};
use crate::{
html::element::HtmlElement, prelude::Render, view::add_attr::AddAnyAttr,
};
use std::marker::PhantomData;
pub trait NodeRefContainer<E>: Send + Clone
where
E: ElementType,
{
fn load(self, el: &crate::renderer::types::Element);
}
#[derive(Debug)]
pub struct NodeRefAttr<E, C> {
container: C,
ty: PhantomData<E>,
}
impl<E, C> Clone for NodeRefAttr<E, C>
where
C: Clone,
{
fn clone(&self) -> Self {
Self {
container: self.container.clone(),
ty: PhantomData,
}
}
}
pub fn node_ref<E, C>(container: C) -> NodeRefAttr<E, C>
where
E: ElementType,
C: NodeRefContainer<E>,
{
NodeRefAttr {
container,
ty: PhantomData,
}
}
impl<E, C> Attribute for NodeRefAttr<E, C>
where
E: ElementType,
C: NodeRefContainer<E>,
crate::renderer::types::Element: PartialEq,
{
const MIN_LENGTH: usize = 0;
type AsyncOutput = Self;
type State = crate::renderer::types::Element;
type Cloneable = ();
type CloneableOwned = ();
#[inline(always)]
fn html_len(&self) -> usize {
0
}
fn to_html(
self,
_buf: &mut String,
_class: &mut String,
_style: &mut String,
_inner_html: &mut String,
) {
}
fn hydrate<const FROM_SERVER: bool>(
self,
el: &crate::renderer::types::Element,
) -> Self::State {
self.container.load(el);
el.to_owned()
}
fn build(self, el: &crate::renderer::types::Element) -> Self::State {
self.container.load(el);
el.to_owned()
}
fn rebuild(self, state: &mut Self::State) {
self.container.load(state);
}
fn into_cloneable(self) -> Self::Cloneable {
panic!("node_ref should not be spread across multiple elements.");
}
fn into_cloneable_owned(self) -> Self::Cloneable {
panic!("node_ref should not be spread across multiple elements.");
}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
}
}
impl<E, C> NextAttribute for NodeRefAttr<E, C>
where
E: ElementType,
C: NodeRefContainer<E>,
crate::renderer::types::Element: PartialEq,
{
type Output<NewAttr: Attribute> = (Self, NewAttr);
fn add_any_attr<NewAttr: Attribute>(
self,
new_attr: NewAttr,
) -> Self::Output<NewAttr> {
(self, new_attr)
}
}
pub trait NodeRefAttribute<E, C>
where
E: ElementType,
C: NodeRefContainer<E>,
crate::renderer::types::Element: PartialEq,
{
fn node_ref(
self,
container: C,
) -> <Self as AddAnyAttr>::Output<NodeRefAttr<E, C>>
where
Self: Sized + AddAnyAttr,
<Self as AddAnyAttr>::Output<NodeRefAttr<E, C>>: Render,
{
self.add_any_attr(node_ref(container))
}
}
impl<E, At, Ch, C> NodeRefAttribute<E, C> for HtmlElement<E, At, Ch>
where
E: ElementType,
At: Attribute,
Ch: Render,
C: NodeRefContainer<E>,
crate::renderer::types::Element: PartialEq,
{
}