chore: tweak generic arguments and iterators in rsx

This commit is contained in:
Jonathan Kelley committed 2022-11-15 20:58:56 -08:00
1 parent e8ae830cf2
commit e09b6bf813
7 files changed
+93 -66

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@ fn app(cx: Scope) -> Element {
oninput: move |e| script.set(e.value.clone()), oninput: move |e| script.set(e.value.clone()),
} }
button { button {
onclick: move |_| eval(script), onclick: move |_| eval(script.to_string()),
"Execute" "Execute"
} }
} }
+1 -1
View File
@@ -72,7 +72,7 @@ fn app(cx: Scope) -> Element {
td { class:"col-md-1" } td { class:"col-md-1" }
td { class:"col-md-1", "{item.key}" } td { class:"col-md-1", "{item.key}" }
td { class:"col-md-1", onclick: move |_| selected.set(Some(id)), td { class:"col-md-1", onclick: move |_| selected.set(Some(id)),
a { class: "lbl", item.labels } a { class: "lbl", "{item.labels[0]}{item.labels[1]}{item.labels[2]}" }
} }
td { class: "col-md-1", td { class: "col-md-1",
a { class: "remove", onclick: move |_| { items.write().remove(id); }, a { class: "remove", onclick: move |_| { items.write().remove(id); },
+19
View File
@@ -0,0 +1,19 @@
use std::fmt::Display;
use dioxus::prelude::*;
fn main() {
dioxus_desktop::launch(app);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
generic_child::<i32>{}
})
}
fn generic_child<T>(cx: Scope) -> Element {
cx.render(rsx! {
div {}
})
}
+1 -1
View File
@@ -183,7 +183,7 @@ fn app(cx: Scope) -> Element {
// Components can be generic too // Components can be generic too
// This component takes i32 type to give you typed input // This component takes i32 type to give you typed input
TypedInput::<TypedInputProps<i32>> {} TypedInput::<i32> {}
// Type inference can be used too // Type inference can be used too
TypedInput { initial: 10.0 } TypedInput { initial: 10.0 }
+3 -2
View File
@@ -8,11 +8,12 @@ fn app(cx: Scope) -> Element {
cx.render(rsx!( cx.render(rsx!(
// Use Map directly to lazily pull elements // Use Map directly to lazily pull elements
(0..10).map(|f| rsx! { "{f}" }), (0..10).map(|f| rsx! { "{f}" }),
// Collect into an intermediate collection if necessary // Collect into an intermediate collection if necessary, and call into_iter
["a", "b", "c"] ["a", "b", "c"]
.into_iter() .into_iter()
.map(|f| rsx! { "{f}" }) .map(|f| rsx! { "{f}" })
.collect::<Vec<_>>(), .collect::<Vec<_>>()
.into_iter(),
// Use optionals // Use optionals
Some(rsx! { "Some" }), Some(rsx! { "Some" }),
)) ))
+61 -59
View File
@@ -41,25 +41,11 @@ impl ScopeState {
} }
} }
pub fn fragment_from_iter<'a, 'c, I, J>( pub fn fragment_from_iter<'a, 'c, I>(
&'a self, &'a self,
node_iter: impl IntoVNode<'a, I, J> + 'c, node_iter: impl IntoDynNode<'a, I> + 'c,
) -> DynamicNode { ) -> DynamicNode {
node_iter.into_vnode(self) node_iter.into_vnode(self)
// let mut bump_vec = bumpalo::vec![in self.bump();];
// for item in it {
// bump_vec.push(item.into_vnode(self));
// }
// match bump_vec.len() {
// 0 => DynamicNode::Placeholder(Cell::new(ElementId(0))),
// _ => DynamicNode::Fragment {
// inner: false,
// nodes: bump_vec.into_bump_slice(),
// },
// }
} }
/// Create a new [`Attribute`] /// Create a new [`Attribute`]
@@ -155,46 +141,65 @@ impl<'a> RenderReturn<'a> {
} }
} }
pub trait IntoVNode<'a, A = (), J = ()> { pub trait IntoDynNode<'a, A = ()> {
fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a>; fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a>;
} }
impl<'a, 'b> IntoVNode<'a> for VNode<'a> { impl<'a, 'b> IntoDynNode<'a> for () {
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> { fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
todo!() todo!()
// self // self
} }
} }
impl<'a, 'b> IntoDynNode<'a> for VNode<'a> {
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
// DynamicNode::Fragment { nodes: cx., inner: () }
todo!()
}
}
impl<'a, 'b> IntoVNode<'a> for LazyNodes<'a, 'b> { impl<'a, 'b, T: IntoDynNode<'a>> IntoDynNode<'a> for Option<T> {
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
// DynamicNode::Fragment { nodes: cx., inner: () }
todo!()
}
}
impl<'a, 'b, T: IntoDynNode<'a>> IntoDynNode<'a> for &Option<T> {
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
// DynamicNode::Fragment { nodes: cx., inner: () }
todo!()
}
}
impl<'a, 'b> IntoDynNode<'a> for LazyNodes<'a, 'b> {
fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> { fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
todo!() DynamicNode::Fragment {
// self.call(cx) nodes: cx.bump().alloc([self.call(cx)]),
inner: false,
}
} }
} }
impl<'b> IntoVNode<'_> for &'b str { impl<'b> IntoDynNode<'_> for &'b str {
fn into_vnode(self, cx: &ScopeState) -> DynamicNode { fn into_vnode(self, cx: &ScopeState) -> DynamicNode {
// cx.text(format_args!("{}", self)) cx.text(format_args!("{}", self))
todo!()
} }
} }
impl IntoVNode<'_> for String { impl IntoDynNode<'_> for String {
fn into_vnode(self, cx: &ScopeState) -> DynamicNode { fn into_vnode(self, cx: &ScopeState) -> DynamicNode {
// cx.text(format_args!("{}", self)) cx.text(format_args!("{}", self))
todo!()
} }
} }
impl<'b> IntoVNode<'b> for Arguments<'_> { impl<'b> IntoDynNode<'b> for Arguments<'_> {
fn into_vnode(self, cx: &'b ScopeState) -> DynamicNode<'b> { fn into_vnode(self, cx: &'b ScopeState) -> DynamicNode<'b> {
// cx.text(self) cx.text(self)
todo!()
} }
} }
impl<'a, 'b> IntoVNode<'a> for &VNode<'a> { impl<'a, 'b> IntoDynNode<'a> for &VNode<'a> {
fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> { fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
todo!() todo!()
// VNode { // VNode {
@@ -209,46 +214,43 @@ impl<'a, 'b> IntoVNode<'a> for &VNode<'a> {
} }
} }
pub trait IntoTemplate<'a> {
fn into_template(self, _cx: &'a ScopeState) -> VNode<'a>;
}
impl<'a, 'b> IntoTemplate<'a> for VNode<'a> {
fn into_template(self, _cx: &'a ScopeState) -> VNode<'a> {
self
}
}
impl<'a, 'b> IntoTemplate<'a> for LazyNodes<'a, 'b> {
fn into_template(self, cx: &'a ScopeState) -> VNode<'a> {
self.call(cx)
}
}
// Note that we're using the E as a generic but this is never crafted anyways. // Note that we're using the E as a generic but this is never crafted anyways.
pub struct FromNodeIterator; pub struct FromNodeIterator;
impl<'a, T, I, E> IntoVNode<'a, FromNodeIterator, E> for T impl<'a, T, I> IntoDynNode<'a, FromNodeIterator> for T
where where
T: IntoIterator<Item = I>, T: Iterator<Item = I>,
I: IntoVNode<'a, E>, I: IntoTemplate<'a>,
{ {
fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> { fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
let mut nodes = bumpalo::collections::Vec::new_in(cx.bump()); let mut nodes = bumpalo::collections::Vec::new_in(cx.bump());
for node in self { for node in self {
nodes.push(node.into_vnode(cx)); nodes.push(node.into_template(cx));
} }
let children = nodes.into_bump_slice(); let children = nodes.into_bump_slice();
// if cfg!(debug_assertions) && children.len() > 1 && children.last().unwrap().key().is_none() match children.len() {
// { 0 => DynamicNode::Placeholder(Cell::new(ElementId(0))),
// let bt = backtrace::Backtrace::new(); _ => DynamicNode::Fragment {
// let bt = "no backtrace available"; inner: false,
nodes: children,
// // todo: make the backtrace prettier or remove it altogether },
// log::error!( }
// r#"
// Warning: Each child in an array or iterator should have a unique "key" prop.
// Not providing a key will lead to poor performance with lists.
// See docs.rs/dioxus for more information.
// -------------
// {:?}
// "#,
// bt
// );
// }
todo!()
// VNode::Fragment(cx.bump.alloc(VFragment {
// children,
// placeholder: Default::default(),
// key: None,
// }))
} }
} }
+7 -2
View File
@@ -154,7 +154,7 @@ impl ToTokens for Component {
} }
None => { None => {
let mut toks = match prop_gen_args { let mut toks = match prop_gen_args {
Some(gen_args) => quote! { fc_to_builder #gen_args(#name) }, Some(gen_args) => quote! { fc_to_builder(#name #gen_args) },
None => quote! { fc_to_builder(#name) }, None => quote! { fc_to_builder(#name) },
}; };
for field in &self.fields { for field in &self.fields {
@@ -187,9 +187,14 @@ impl ToTokens for Component {
let fn_name = self.name.segments.last().unwrap().ident.to_string(); let fn_name = self.name.segments.last().unwrap().ident.to_string();
let gen_name = match &self.prop_gen_args {
Some(gen) => quote! { #name #gen },
None => quote! { #name },
};
tokens.append_all(quote! { tokens.append_all(quote! {
__cx.component( __cx.component(
#name, #gen_name,
#builder, #builder,
#fn_name #fn_name
) )