Browse Source

Feat: wire up props macro

Jonathan Kelley 4 years ago
parent
commit
37f5a7ad33

+ 50 - 22
packages/core-macro/src/rsxt.rs

@@ -132,7 +132,7 @@ impl Parse for Node {
 
 struct Component {
     name: Ident,
-    body: Vec<Field>,
+    body: Vec<ComponentField>,
     // attrs: Vec<Attr>,
     children: MaybeExpr<Vec<Node>>,
 }
@@ -147,13 +147,19 @@ impl ToTokens for ToToksCtx<&Component> {
         //     self.recurse(attr).to_tokens(&mut toks);
         // }
 
-        let body = &self.inner.body;
-        // panic!("tokens are {:#?}", toks);
+        let mut builder = quote! {
+            fc_to_builder(#name)
+        };
 
-        // tokens.append_all(quote! {
-        //     dioxus::builder::virtual_child(ctx, #name{ #body, ___p: PhantomData{} })
-        //     // dioxus::builder::ElementBuilder::new(ctx, #name)
-        // });
+        for field in &self.inner.body {
+            builder.append_all(quote! {#field});
+        }
+
+        builder.append_all(quote! {
+            .build()
+        });
+
+        // panic!("tokens are {:#?}", toks);
 
         // no children right now
 
@@ -179,6 +185,9 @@ impl ToTokens for ToToksCtx<&Component> {
         // tokens.append_all(quote! {
         //     .finish()
         // });
+        let toks = tokens.append_all(quote! {
+            dioxus::builder::virtual_child(ctx, #name, #builder)
+        });
     }
 }
 
@@ -199,18 +208,21 @@ impl Parse for Component {
         let content: ParseBuffer;
         syn::braced!(content in s);
 
-        let mut body: Vec<Field> = Vec::new();
-        let mut attrs = Vec::new();
+        let mut body: Vec<ComponentField> = Vec::new();
         let mut children: Vec<Node> = Vec::new();
 
-        parse_element_content(content, &mut attrs, &mut children);
+        // parse_element_content(content, &mut attrs, &mut children);
 
-        // 'parsing: loop {
-        //     // [1] Break if empty
-        //     if content.is_empty() {
-        //         break 'parsing;
-        //     }
-        // }
+        'parsing: loop {
+            // [1] Break if empty
+            if content.is_empty() {
+                break 'parsing;
+            }
+
+            if let Ok(field) = content.parse::<ComponentField>() {
+                body.push(field);
+            }
+        }
 
         // let body = content.parse()?;
 
@@ -231,20 +243,36 @@ impl Parse for Component {
 }
 
 // the struct's fields info
-pub struct Field {
+pub struct ComponentField {
     name: Ident,
-    content: Ident,
+    content: Expr,
 }
 
-impl Parse for Field {
+impl Parse for ComponentField {
     fn parse(input: ParseStream) -> Result<Self> {
-        todo!()
+        let mut name = Ident::parse_any(input)?;
+        let name_str = name.to_string();
+        input.parse::<Token![:]>()?;
+        let content = input.parse()?;
+
+        // consume comma if it exists
+        // we don't actually care if there *are* commas between attrs
+        if input.peek(Token![,]) {
+            let _ = input.parse::<Token![,]>();
+        }
+
+        Ok(Self { name, content })
     }
 }
 
-impl ToTokens for ToToksCtx<&Field> {
+impl ToTokens for &ComponentField {
+    // impl ToTokens for ToToksCtx<&ComponentField> {
     fn to_tokens(&self, tokens: &mut TokenStream2) {
-        todo!()
+        let name = &self.name;
+        let content = &self.content;
+        tokens.append_all(quote! {
+            .#name(#content)
+        })
     }
 }
 

+ 11 - 8
packages/core/examples/borrowed.rs

@@ -9,7 +9,7 @@ fn main() {}
 
 use std::fmt::Debug;
 
-use dioxus_core::{component::Properties, prelude::*};
+use dioxus_core::prelude::*;
 
 struct Props {
     items: Vec<ListItem>,
@@ -32,11 +32,12 @@ fn app(ctx: Context, props: &Props) -> DomTree {
             // <ChildItem item=child hanldler=setter />
             root = root.child(builder::virtual_child(
                 c,
-                ChildProps {
-                    item: child,
-                    item_handler: setter,
-                },
-                child_item,
+                ChildItem,
+                // create the props with nothing but the fc<T>
+                fc_to_builder(ChildItem)
+                    .item(child)
+                    .item_handler(setter)
+                    .build(),
             ));
         }
         root.finish()
@@ -64,7 +65,9 @@ struct ChildProps<'a> {
 
 impl PartialEq for ChildProps<'_> {
     fn eq(&self, other: &Self) -> bool {
-        todo!()
+        // assume the dyn fn is never stable -
+        // wrap with use_callback if it's an issue for you
+        false
     }
 }
 
@@ -75,7 +78,7 @@ impl<'a> Properties for ChildProps<'a> {
     }
 }
 
-fn child_item(ctx: Context, props: &ChildProps) -> DomTree {
+fn ChildItem(ctx: Context, props: &ChildProps) -> DomTree {
     todo!()
     //     ctx.render(rsx! {
     //         div {

+ 22 - 26
packages/core/examples/fc.rs

@@ -1,41 +1,37 @@
+use dioxus_core::component::fc_to_builder;
 use dioxus_core::prelude::*;
-
 use dioxus_core_macro::fc;
 
 use std::marker::PhantomData;
-// #[derive(PartialEq)]
-// pub struct Example<'a> {
-//     b: &'a str,
-//     ___p: std::marker::PhantomData<&'a ()>,
-// }
-
-// impl<'a> FC for Example<'a> {
-//     fn render(ctx: Context<'_>, props: &Example<'a>) -> DomTree {
-//         let Example { b, .. } = props;
-//         {
-//             ctx.render(rsx! {
-//                 div { "abcd {b}" }
-//             })
-//         }
-//     }
-// }
-
-// always try to fill in with Default
 
-// #[fc]
-fn Example(ctx: Context, a: &str, b: &str, c: &str) -> DomTree {
+static BLAH: FC<()> = |ctx, props| {
+    let g = "asd".to_string();
     ctx.render(rsx! {
         div {
             SomeComponent {
-                a: "123"
+                some_field: g
+                abc123: 10,
             }
         }
     })
-}
+};
 
-// #[fc]
-fn SomeComponent(ctx: Context, a: &str, b: &str) -> DomTree {
-    todo!()
+#[derive(PartialEq, Props)]
+pub struct ExampleProps {
+    some_field: String,
 }
 
+static SomeComponent: FC<ExampleProps> = |ctx, props| {
+    ctx.render(rsx! {
+        div { }
+    })
+};
+
 fn main() {}
+
+impl Properties for ExampleProps {
+    type Builder = ExamplePropsBuilder<((),)>;
+    fn builder() -> Self::Builder {
+        ExampleProps::builder()
+    }
+}

+ 1 - 1
packages/core/src/component.rs

@@ -15,7 +15,7 @@ pub trait Properties: PartialEq {
 
 pub struct EmptyBuilder;
 impl EmptyBuilder {
-    pub fn build() -> () {
+    pub fn build(self) -> () {
         ()
     }
 }

+ 1 - 1
packages/core/src/lib.rs

@@ -130,7 +130,7 @@ pub(crate) mod innerlude {
 /// Re-export common types for ease of development use.
 /// Essential when working with the html! macro
 pub mod prelude {
-    // pub use crate::component::Properties;
+    pub use crate::component::{fc_to_builder, Properties};
     pub use crate::context::Context;
     use crate::nodes;
     pub use crate::virtual_dom::VirtualDom;

+ 2 - 1
packages/core/src/nodebuilder.rs

@@ -528,9 +528,10 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
 // _props: T
 pub fn virtual_child<'a, 'b, T: crate::innerlude::Properties>(
     ctx: &'b NodeCtx<'a>,
-    p: T,
     f: FC<T>,
+    p: T,
 ) -> VNode<'a> {
+    // crate::nodes::VComponent
     todo!()
     // VNode::Component()
 }