use super::{
add_attr::AddAnyAttr, Mountable, Position, PositionState, Render,
RenderHtml, ToTemplate,
};
use crate::{
html::attribute::{any_attribute::AnyAttribute, Attribute},
hydration::Cursor,
renderer::Rndr,
};
pub struct ViewTemplate<V> {
view: V,
}
impl<V> ViewTemplate<V>
where
V: Render + ToTemplate + 'static,
{
pub fn new(view: V) -> Self {
Self { view }
}
fn to_template() -> crate::renderer::types::TemplateElement {
Rndr::get_template::<V>()
}
}
impl<V> Render for ViewTemplate<V>
where
V: Render + RenderHtml + ToTemplate + 'static,
V::State: Mountable,
{
type State = V::State;
fn build(self) -> Self::State {
let tpl = Self::to_template();
let contents = Rndr::clone_template(&tpl);
self.view
.hydrate::<false>(&Cursor::new(contents), &Default::default())
}
fn rebuild(self, state: &mut Self::State) {
self.view.rebuild(state)
}
}
impl<V> AddAnyAttr for ViewTemplate<V>
where
V: RenderHtml + ToTemplate + 'static,
V::State: Mountable,
{
type Output<SomeNewAttr: Attribute> = ViewTemplate<V>;
fn add_any_attr<NewAttr: Attribute>(
self,
_attr: NewAttr,
) -> Self::Output<NewAttr> {
panic!("AddAnyAttr not supported on ViewTemplate");
}
}
impl<V> RenderHtml for ViewTemplate<V>
where
V: RenderHtml + ToTemplate + 'static,
V::State: Mountable,
{
type AsyncOutput = V::AsyncOutput;
type Owned = V::Owned;
const MIN_LENGTH: usize = V::MIN_LENGTH;
fn to_html_with_buf(
self,
buf: &mut String,
position: &mut Position,
escape: bool,
mark_branches: bool,
extra_attrs: Vec<AnyAttribute>,
) {
self.view.to_html_with_buf(
buf,
position,
escape,
mark_branches,
extra_attrs,
)
}
fn hydrate<const FROM_SERVER: bool>(
self,
cursor: &Cursor,
position: &PositionState,
) -> Self::State {
self.view.hydrate::<FROM_SERVER>(cursor, position)
}
fn dry_resolve(&mut self) {
self.view.dry_resolve();
}
async fn resolve(self) -> Self::AsyncOutput {
self.view.resolve().await
}
fn into_owned(self) -> Self::Owned {
self.view.into_owned()
}
}
impl<V> ToTemplate for ViewTemplate<V>
where
V: RenderHtml + ToTemplate + 'static,
V::State: Mountable,
{
const TEMPLATE: &'static str = V::TEMPLATE;
fn to_template(
buf: &mut String,
class: &mut String,
style: &mut String,
inner_html: &mut String,
position: &mut Position,
) {
V::to_template(buf, class, style, inner_html, position);
}
}