mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-14 00:27:12 +00:00
feat: implement rendering traits for fixed-size arrays (#3174)
This commit is contained in:
parent
3a8508df6c
commit
d9f52dad76
1 changed files with 144 additions and 0 deletions
|
@ -336,3 +336,147 @@ where
|
|||
VecState { states, marker }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Render for [T; N]
|
||||
where
|
||||
T: Render,
|
||||
{
|
||||
type State = ArrayState<T::State, N>;
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
Self::State {
|
||||
states: self.map(T::build),
|
||||
}
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
let Self::State { states } = state;
|
||||
let old = states;
|
||||
// this is an unkeyed diff
|
||||
self.into_iter()
|
||||
.zip(old.iter_mut())
|
||||
.for_each(|(new, old)| T::rebuild(new, old));
|
||||
}
|
||||
}
|
||||
|
||||
/// Retained view state for a `Vec<_>`.
|
||||
pub struct ArrayState<T, const N: usize>
|
||||
where
|
||||
T: Mountable,
|
||||
{
|
||||
states: [T; N],
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Mountable for ArrayState<T, N>
|
||||
where
|
||||
T: Mountable,
|
||||
{
|
||||
fn unmount(&mut self) {
|
||||
self.states.iter_mut().for_each(Mountable::unmount);
|
||||
}
|
||||
|
||||
fn mount(
|
||||
&mut self,
|
||||
parent: &crate::renderer::types::Element,
|
||||
marker: Option<&crate::renderer::types::Node>,
|
||||
) {
|
||||
for state in self.states.iter_mut() {
|
||||
state.mount(parent, marker);
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_before_this(&self, child: &mut dyn Mountable) -> bool {
|
||||
if let Some(first) = self.states.first() {
|
||||
first.insert_before_this(child)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T, const N: usize> AddAnyAttr for [T; N]
|
||||
where
|
||||
T: AddAnyAttr,
|
||||
{
|
||||
type Output<SomeNewAttr: Attribute> =
|
||||
[<T as AddAnyAttr>::Output<SomeNewAttr::Cloneable>; N];
|
||||
|
||||
fn add_any_attr<NewAttr: Attribute>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
) -> Self::Output<NewAttr>
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml,
|
||||
{
|
||||
let attr = attr.into_cloneable();
|
||||
self.map(|n| n.add_any_attr(attr.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> RenderHtml for [T; N]
|
||||
where
|
||||
T: RenderHtml,
|
||||
{
|
||||
type AsyncOutput = [T::AsyncOutput; N];
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn dry_resolve(&mut self) {
|
||||
for inner in self.iter_mut() {
|
||||
inner.dry_resolve();
|
||||
}
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
futures::future::join_all(self.into_iter().map(T::resolve))
|
||||
.await
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap_or_else(|_| unreachable!())
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
self.iter().map(RenderHtml::html_len).sum::<usize>()
|
||||
}
|
||||
|
||||
fn to_html_with_buf(
|
||||
self,
|
||||
buf: &mut String,
|
||||
position: &mut Position,
|
||||
escape: bool,
|
||||
mark_branches: bool,
|
||||
) {
|
||||
for child in self.into_iter() {
|
||||
child.to_html_with_buf(buf, position, escape, mark_branches);
|
||||
}
|
||||
}
|
||||
|
||||
fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
|
||||
self,
|
||||
buf: &mut StreamBuilder,
|
||||
position: &mut Position,
|
||||
escape: bool,
|
||||
mark_branches: bool,
|
||||
) where
|
||||
Self: Sized,
|
||||
{
|
||||
for child in self.into_iter() {
|
||||
child.to_html_async_with_buf::<OUT_OF_ORDER>(
|
||||
buf,
|
||||
position,
|
||||
escape,
|
||||
mark_branches,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
cursor: &Cursor,
|
||||
position: &PositionState,
|
||||
) -> Self::State {
|
||||
let states =
|
||||
self.map(|child| child.hydrate::<FROM_SERVER>(cursor, position));
|
||||
ArrayState { states }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue