mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-30 08:00:21 +00:00
Feat: building large apps, revamp macro
This commit is contained in:
parent
5791e49700
commit
9f7f43b661
20 changed files with 386 additions and 293 deletions
|
@ -6,6 +6,7 @@ members = [
|
||||||
"packages/web",
|
"packages/web",
|
||||||
"packages/liveview",
|
"packages/liveview",
|
||||||
"packages/3d",
|
"packages/3d",
|
||||||
|
"packages/docsite",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Built-in
|
# Built-in
|
||||||
|
|
|
@ -58,11 +58,11 @@ impl ToTokens for HtmlRender {
|
||||||
|
|
||||||
// create a lazy tree that accepts a bump allocator
|
// create a lazy tree that accepts a bump allocator
|
||||||
let final_tokens = quote! {
|
let final_tokens = quote! {
|
||||||
move |ctx| {
|
dioxus::prelude::LazyNodes::new(move |ctx| {
|
||||||
let bump = ctx.bump;
|
let bump = ctx.bump;
|
||||||
|
|
||||||
#new_toks
|
#new_toks
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
final_tokens.to_tokens(out_tokens);
|
final_tokens.to_tokens(out_tokens);
|
||||||
|
|
|
@ -30,6 +30,10 @@ ctx.render(rsx!{
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
optionally, include the allocator directly
|
||||||
|
|
||||||
|
rsx!(ctx, div { "hello"} )
|
||||||
|
|
||||||
each element is given by tag { [Attr] }
|
each element is given by tag { [Attr] }
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -50,18 +54,31 @@ use {
|
||||||
// Parse any stream coming from the rsx! macro
|
// Parse any stream coming from the rsx! macro
|
||||||
// ==============================================
|
// ==============================================
|
||||||
pub struct RsxRender {
|
pub struct RsxRender {
|
||||||
|
custom_context: Option<Ident>,
|
||||||
el: Element,
|
el: Element,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for RsxRender {
|
impl Parse for RsxRender {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
|
let fork = input.fork();
|
||||||
|
|
||||||
|
let custom_context = fork
|
||||||
|
.parse::<Ident>()
|
||||||
|
.and_then(|ident| {
|
||||||
|
fork.parse::<Token![,]>().map(|_| {
|
||||||
|
input.advance_to(&fork);
|
||||||
|
ident
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
|
||||||
// cannot accept multiple elements
|
// cannot accept multiple elements
|
||||||
// can only accept one root per component
|
// can only accept one root per component
|
||||||
// fragments can be used as
|
// fragments can be used as
|
||||||
// todo
|
// todo
|
||||||
// enable fragements by autocoerrcing into list
|
// enable fragements by autocoerrcing into list
|
||||||
let el: Element = input.parse()?;
|
let el: Element = input.parse()?;
|
||||||
Ok(Self { el })
|
Ok(Self { el, custom_context })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,11 +88,19 @@ impl ToTokens for RsxRender {
|
||||||
// let new_toks = ToToksCtx::new(&self.kind).to_token_stream();
|
// let new_toks = ToToksCtx::new(&self.kind).to_token_stream();
|
||||||
|
|
||||||
// create a lazy tree that accepts a bump allocator
|
// create a lazy tree that accepts a bump allocator
|
||||||
let final_tokens = quote! {
|
let final_tokens = match &self.custom_context {
|
||||||
move |ctx: &dioxus::prelude::NodeCtx<'_>| -> dioxus::prelude::VNode<'_>{
|
Some(ident) => quote! {
|
||||||
|
#ident.render(dioxus::prelude::LazyNodes::new(move |ctx|{
|
||||||
let bump = ctx.bump;
|
let bump = ctx.bump;
|
||||||
#new_toks
|
#new_toks
|
||||||
}
|
}))
|
||||||
|
},
|
||||||
|
None => quote! {
|
||||||
|
dioxus::prelude::LazyNodes::new(move |ctx|{
|
||||||
|
let bump = ctx.bump;
|
||||||
|
#new_toks
|
||||||
|
})
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
final_tokens.to_tokens(out_tokens);
|
final_tokens.to_tokens(out_tokens);
|
||||||
|
@ -102,29 +127,32 @@ impl ToTokens for ToToksCtx<&Node> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Node {
|
impl Parse for Node {
|
||||||
fn parse(s: ParseStream) -> Result<Self> {
|
fn parse(stream: ParseStream) -> Result<Self> {
|
||||||
let fork1 = s.fork();
|
let fork1 = stream.fork();
|
||||||
let fork2 = s.fork();
|
let fork2 = stream.fork();
|
||||||
|
|
||||||
// todo: map issues onto the second fork if any arise
|
// todo: map issues onto the second fork if any arise
|
||||||
// it's unlikely that textnodes or components would fail?
|
// it's unlikely that textnodes or components would fail?
|
||||||
|
|
||||||
let ret = if let Ok(text) = fork1.parse::<TextNode>() {
|
let ret = if let Ok(text) = fork1.parse::<TextNode>() {
|
||||||
s.advance_to(&fork1);
|
stream.advance_to(&fork1);
|
||||||
Self::Text(text)
|
Self::Text(text)
|
||||||
} else if let Ok(element) = fork2.parse::<Element>() {
|
} else if let Ok(element) = fork2.parse::<Element>() {
|
||||||
s.advance_to(&fork2);
|
stream.advance_to(&fork2);
|
||||||
Self::Element(element)
|
Self::Element(element)
|
||||||
} else if let Ok(comp) = s.parse::<Component>() {
|
} else if let Ok(comp) = stream.parse::<Component>() {
|
||||||
Self::Component(comp)
|
Self::Component(comp)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::new(s.span(), "Failed to parse as a valid child"));
|
return Err(Error::new(
|
||||||
|
stream.span(),
|
||||||
|
"Failed to parse as a valid child",
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
// consume comma if it exists
|
// consume comma if it exists
|
||||||
// we don't actually care if there *are* commas after elements/text
|
// we don't actually care if there *are* commas after elements/text
|
||||||
if s.peek(Token![,]) {
|
if stream.peek(Token![,]) {
|
||||||
let _ = s.parse::<Token![,]>();
|
let _ = stream.parse::<Token![,]>();
|
||||||
}
|
}
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
@ -301,7 +329,7 @@ impl ToTokens for ToToksCtx<&Element> {
|
||||||
}
|
}
|
||||||
match &self.inner.children {
|
match &self.inner.children {
|
||||||
MaybeExpr::Expr(expr) => tokens.append_all(quote! {
|
MaybeExpr::Expr(expr) => tokens.append_all(quote! {
|
||||||
.children(#expr)
|
.iter_child(#expr)
|
||||||
}),
|
}),
|
||||||
MaybeExpr::Literal(nodes) => {
|
MaybeExpr::Literal(nodes) => {
|
||||||
let mut children = nodes.iter();
|
let mut children = nodes.iter();
|
||||||
|
@ -340,7 +368,7 @@ impl Parse for Element {
|
||||||
|
|
||||||
let mut attrs: Vec<Attr> = vec![];
|
let mut attrs: Vec<Attr> = vec![];
|
||||||
let mut children: Vec<Node> = vec![];
|
let mut children: Vec<Node> = vec![];
|
||||||
parse_element_content(content, &mut attrs, &mut children);
|
parse_element_content(content, &mut attrs, &mut children)?;
|
||||||
|
|
||||||
let children = MaybeExpr::Literal(children);
|
let children = MaybeExpr::Literal(children);
|
||||||
|
|
||||||
|
@ -353,7 +381,11 @@ impl Parse for Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used by both vcomponet and velement to parse the contents of the elements into attras and children
|
// used by both vcomponet and velement to parse the contents of the elements into attras and children
|
||||||
fn parse_element_content(content: ParseBuffer, attrs: &mut Vec<Attr>, children: &mut Vec<Node>) {
|
fn parse_element_content(
|
||||||
|
stream: ParseBuffer,
|
||||||
|
attrs: &mut Vec<Attr>,
|
||||||
|
children: &mut Vec<Node>,
|
||||||
|
) -> Result<()> {
|
||||||
'parsing: loop {
|
'parsing: loop {
|
||||||
// todo move this around into a more functional style
|
// todo move this around into a more functional style
|
||||||
// [1] Break if empty
|
// [1] Break if empty
|
||||||
|
@ -363,38 +395,47 @@ fn parse_element_content(content: ParseBuffer, attrs: &mut Vec<Attr>, children:
|
||||||
// [last] Fail if none worked
|
// [last] Fail if none worked
|
||||||
|
|
||||||
// [1] Break if empty
|
// [1] Break if empty
|
||||||
if content.is_empty() {
|
if stream.is_empty() {
|
||||||
break 'parsing;
|
break 'parsing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [2] Try to consume an attr
|
// [2] Try to consume an attr
|
||||||
let fork = content.fork();
|
let fork = stream.fork();
|
||||||
if let Ok(attr) = fork.parse::<Attr>() {
|
if let Ok(attr) = fork.parse::<Attr>() {
|
||||||
// make sure to advance or your computer will become a spaceheater :)
|
// make sure to advance or your computer will become a spaceheater :)
|
||||||
content.advance_to(&fork);
|
stream.advance_to(&fork);
|
||||||
attrs.push(attr);
|
attrs.push(attr);
|
||||||
continue 'parsing;
|
continue 'parsing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [3] Try to consume a child node
|
// [3] Try to consume a child node
|
||||||
let fork = content.fork();
|
let fork = stream.fork();
|
||||||
if let Ok(node) = fork.parse::<Node>() {
|
if let Ok(node) = fork.parse::<Node>() {
|
||||||
// make sure to advance or your computer will become a spaceheater :)
|
// make sure to advance or your computer will become a spaceheater :)
|
||||||
content.advance_to(&fork);
|
stream.advance_to(&fork);
|
||||||
children.push(node);
|
children.push(node);
|
||||||
continue 'parsing;
|
continue 'parsing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [4] TODO: Parsing brackets
|
// [4] TODO: Parsing brackets
|
||||||
|
|
||||||
|
if stream.peek(token::Brace) {
|
||||||
|
// this can fail (mismatched brackets)
|
||||||
|
let content;
|
||||||
|
syn::braced!(content in &stream);
|
||||||
|
continue 'parsing;
|
||||||
// let fork = content.fork();
|
// let fork = content.fork();
|
||||||
|
// stream.advance_to(fork)
|
||||||
|
}
|
||||||
// if let Ok(el) = fork.parse() {
|
// if let Ok(el) = fork.parse() {
|
||||||
// children.push(el);
|
// children.push(el);
|
||||||
// continue 'parsing;
|
// continue 'parsing;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// todo: pass a descriptive error onto the offending tokens
|
// todo: pass a descriptive error onto the offending tokens
|
||||||
panic!("Entry is not an attr or element\n {}", content)
|
panic!("Entry is not an attr or element\n {}", stream)
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// =======================================
|
/// =======================================
|
||||||
|
|
|
@ -1,93 +1,17 @@
|
||||||
// //! An alternative function syntax
|
|
||||||
// //!
|
|
||||||
|
|
||||||
// use bumpalo::Bump;
|
|
||||||
// use dioxus_core::prelude::VNode;
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
// struct Context2<'a, P> {
|
use dioxus_core::prelude::*;
|
||||||
// _props: &'a P, // _p: PhantomData<&'a ()>,
|
|
||||||
// rops: &'a P, // _p: PhantomData<&'a ()>,
|
|
||||||
// }
|
|
||||||
// impl<'a, P> Context2<'a, P> {
|
|
||||||
// fn render(self, _f: impl FnOnce(&'a Bump) -> VNode<'a>) -> DTree {
|
|
||||||
// DTree {}
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn props(&self) -> &'a P {
|
static Example: FC<()> = |ctx, props| {
|
||||||
// todo!()
|
ctx.render(dioxus_core::prelude::LazyNodes::new(move |ctx| {
|
||||||
// }
|
let bump = ctx.bump;
|
||||||
|
dioxus::builder::ElementBuilder::new(ctx, "h1")
|
||||||
// pub fn use_hook<'scope, InternalHookState: 'static, Output: 'a>(
|
.children([{
|
||||||
// &'scope self,
|
use bumpalo::core_alloc::fmt::Write;
|
||||||
// _initializer: impl FnOnce() -> InternalHookState,
|
let mut s = bumpalo::collections::String::new_in(bump);
|
||||||
// _runner: impl FnOnce(&'a mut InternalHookState) -> Output,
|
write!(s, "hello");
|
||||||
// _cleanup: impl FnOnce(InternalHookState),
|
dioxus::builder::text2(s)
|
||||||
// ) -> Output {
|
}])
|
||||||
// todo!()
|
.finish()
|
||||||
// }
|
}))
|
||||||
// }
|
};
|
||||||
|
|
||||||
// trait Properties {}
|
|
||||||
|
|
||||||
// struct DTree;
|
|
||||||
// // type FC2<'a, T: 'a> = fn(Context2<T>) -> DTree;
|
|
||||||
// fn virtual_child<'a, T: 'a>(_bump: &'a Bump, _props: T, _f: FC2<T>) -> VNode<'a> {
|
|
||||||
// todo!()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct Props {
|
|
||||||
// c: String,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn Example(ctx: Context2<Props>) -> DTree {
|
|
||||||
// let val = use_state(&ctx, || String::from("asd"));
|
|
||||||
// let props = ctx.props();
|
|
||||||
|
|
||||||
// ctx.render(move |b| {
|
|
||||||
// dioxus_core::nodebuilder::div(b)
|
|
||||||
// .child(dioxus_core::nodebuilder::text(props.c.as_str()))
|
|
||||||
// .child(virtual_child(b, Props2 { a: val }, AltChild))
|
|
||||||
// .finish()
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // #[fc]
|
|
||||||
// fn Example2(ctx: Context2<()>, name: &str, _blah: &str) -> DTree {
|
|
||||||
// let val = use_state(&ctx, || String::from("asd"));
|
|
||||||
|
|
||||||
// ctx.render(move |ctx| {
|
|
||||||
// dioxus_core::builder::ElementBuilder::new(b, "div")
|
|
||||||
// .child(dioxus_core::nodebuilder::text(name))
|
|
||||||
// .child(virtual_child(b, Props2 { a: val }, AltChild))
|
|
||||||
// .finish()
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// type FC2<'a, T> = fn(Context2<T>) -> DTree;
|
|
||||||
|
|
||||||
// // still works if you don't take any references in your props (ie, something copy or cloneable)
|
|
||||||
// static CHILD: FC2<Props2> = |_ctx: Context2<Props2>| {
|
|
||||||
// //
|
|
||||||
// todo!()
|
|
||||||
// };
|
|
||||||
|
|
||||||
// struct Props2<'a> {
|
|
||||||
// a: &'a String,
|
|
||||||
// }
|
|
||||||
// impl Properties for Props2<'_> {}
|
|
||||||
|
|
||||||
// fn AltChild(ctx: Context2<Props2>) -> DTree {
|
|
||||||
// ctx.render(|_b| {
|
|
||||||
// //
|
|
||||||
// todo!()
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn use_state<'a, 'c, P, T: 'static, F: FnOnce() -> T>(
|
|
||||||
// _ctx: &'_ Context2<'a, P>,
|
|
||||||
// _initial_state_fn: F,
|
|
||||||
// ) -> &'a T {
|
|
||||||
// todo!()
|
|
||||||
// }
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct ListItem {
|
||||||
fn app(ctx: Context, props: &Props) -> DomTree {
|
fn app(ctx: Context, props: &Props) -> DomTree {
|
||||||
let (_f, setter) = use_state(&ctx, || 0);
|
let (_f, setter) = use_state(&ctx, || 0);
|
||||||
|
|
||||||
ctx.render(move |c| {
|
ctx.render(dioxus::prelude::LazyNodes::new(move |c| {
|
||||||
let mut root = builder::ElementBuilder::new(c, "div");
|
let mut root = builder::ElementBuilder::new(c, "div");
|
||||||
for child in &props.items {
|
for child in &props.items {
|
||||||
// notice that the child directly borrows from our vec
|
// notice that the child directly borrows from our vec
|
||||||
|
@ -39,7 +39,7 @@ fn app(ctx: Context, props: &Props) -> DomTree {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
root.finish()
|
root.finish()
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
type StateSetter<T> = dyn Fn(T);
|
type StateSetter<T> = dyn Fn(T);
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct Props {
|
||||||
static Example: FC<Props> = |ctx, props| {
|
static Example: FC<Props> = |ctx, props| {
|
||||||
let value = ctx.use_context(|c: &SomeContext| c.items.last().unwrap());
|
let value = ctx.use_context(|c: &SomeContext| c.items.last().unwrap());
|
||||||
|
|
||||||
ctx.render(move |bump| {
|
ctx.render(LazyNodes::new(move |bump| {
|
||||||
builder::ElementBuilder::new(bump, "button")
|
builder::ElementBuilder::new(bump, "button")
|
||||||
.on("click", move |_| {
|
.on("click", move |_| {
|
||||||
println!("Value is {}", props.name);
|
println!("Value is {}", props.name);
|
||||||
|
@ -24,7 +24,7 @@ static Example: FC<Props> = |ctx, props| {
|
||||||
println!("Value is {}", props.name);
|
println!("Value is {}", props.name);
|
||||||
})
|
})
|
||||||
.finish()
|
.finish()
|
||||||
})
|
}))
|
||||||
// ctx.render(html! {
|
// ctx.render(html! {
|
||||||
// <div>
|
// <div>
|
||||||
// <button onclick={move |_| println!("Value is {}", value)} />
|
// <button onclick={move |_| println!("Value is {}", value)} />
|
||||||
|
|
|
@ -18,8 +18,54 @@ pub struct ExampleProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SomeComponent: FC<ExampleProps> = |ctx, _props| {
|
static SomeComponent: FC<ExampleProps> = |ctx, _props| {
|
||||||
ctx.render(rsx! {
|
let blah = rsx! {
|
||||||
div {}
|
div {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = match 1 {
|
||||||
|
1 => ctx.render(rsx! (
|
||||||
|
div {
|
||||||
|
h1 {}
|
||||||
|
h3 {}
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
1 => ctx.render(rsx!( div { "abc" } )),
|
||||||
|
2 => ctx.render(rsx!( div { "abc" } )),
|
||||||
|
3 => ctx.render(rsx!( div { "abc" } )),
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = match 1 {
|
||||||
|
1 => ctx.render(rsx! (
|
||||||
|
div {
|
||||||
|
h1 {}
|
||||||
|
h3 {}
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
1 => ctx.render(rsx!(
|
||||||
|
div { "abc" }
|
||||||
|
)),
|
||||||
|
2 => ctx.render(rsx!(
|
||||||
|
div { "abc" }
|
||||||
|
)),
|
||||||
|
3 => ctx.render(rsx!(
|
||||||
|
div { "abc" }
|
||||||
|
)),
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let i = (0..10).map(|v| {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
"{v}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.render(rsx! {
|
||||||
|
div {
|
||||||
|
""
|
||||||
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ static Header: FC<()> = |ctx, props| {
|
||||||
|
|
||||||
let handler1 = move || println!("Value is {}", inner.current());
|
let handler1 = move || println!("Value is {}", inner.current());
|
||||||
|
|
||||||
ctx.render(|c| {
|
ctx.render(dioxus::prelude::LazyNodes::new(|c| {
|
||||||
builder::ElementBuilder::new(c, "div")
|
builder::ElementBuilder::new(c, "div")
|
||||||
.child(VNode::Component(VComponent::new(
|
.child(VNode::Component(VComponent::new(
|
||||||
Bottom,
|
Bottom,
|
||||||
|
@ -20,7 +20,7 @@ static Header: FC<()> = |ctx, props| {
|
||||||
c.bump.alloc(()),
|
c.bump.alloc(()),
|
||||||
)))
|
)))
|
||||||
.finish()
|
.finish()
|
||||||
})
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
static Bottom: FC<()> = |ctx, props| {
|
static Bottom: FC<()> = |ctx, props| {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::nodes::VNode;
|
use crate::{nodebuilder::IntoDomTree, prelude::*};
|
||||||
use crate::prelude::*;
|
use crate::{nodebuilder::LazyNodes, nodes::VNode};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use hooks::Hook;
|
use hooks::Hook;
|
||||||
use std::{cell::RefCell, future::Future, ops::Deref, rc::Rc, sync::atomic::AtomicUsize};
|
use std::{cell::RefCell, future::Future, ops::Deref, rc::Rc, sync::atomic::AtomicUsize};
|
||||||
|
@ -95,7 +95,10 @@ impl<'a> Context<'a> {
|
||||||
/// ctx.render(lazy_tree)
|
/// ctx.render(lazy_tree)
|
||||||
/// }
|
/// }
|
||||||
///```
|
///```
|
||||||
pub fn render(&self, lazy_nodes: impl FnOnce(&'_ NodeCtx<'a>) -> VNode<'a> + 'a) -> DomTree {
|
pub fn render<F: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a>(
|
||||||
|
&self,
|
||||||
|
lazy_nodes: LazyNodes<'a, F>,
|
||||||
|
) -> DomTree {
|
||||||
let ctx = NodeCtx {
|
let ctx = NodeCtx {
|
||||||
bump: self.bump,
|
bump: self.bump,
|
||||||
scope: self.scope,
|
scope: self.scope,
|
||||||
|
@ -103,7 +106,7 @@ impl<'a> Context<'a> {
|
||||||
listeners: self.listeners,
|
listeners: self.listeners,
|
||||||
};
|
};
|
||||||
|
|
||||||
let safe_nodes = lazy_nodes(&ctx);
|
let safe_nodes = lazy_nodes.into_vnode(&ctx);
|
||||||
let root: VNode<'static> = unsafe { std::mem::transmute(safe_nodes) };
|
let root: VNode<'static> = unsafe { std::mem::transmute(safe_nodes) };
|
||||||
DomTree { root }
|
DomTree { root }
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,12 +160,7 @@ pub mod on {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MouseEvent(pub Box<RawMouseEvent>);
|
pub struct MouseEvent(pub Box<RawMouseEvent>);
|
||||||
impl Deref for MouseEvent {
|
|
||||||
type Target = RawMouseEvent;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
self.0.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RawMouseEvent {
|
pub struct RawMouseEvent {
|
||||||
pub alt_key: bool,
|
pub alt_key: bool,
|
||||||
|
@ -183,6 +178,12 @@ pub mod on {
|
||||||
pub get_modifier_state: GetModifierKey,
|
pub get_modifier_state: GetModifierKey,
|
||||||
// relatedTarget: DOMEventTarget,
|
// relatedTarget: DOMEventTarget,
|
||||||
}
|
}
|
||||||
|
impl Deref for MouseEvent {
|
||||||
|
type Target = RawMouseEvent;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
event_builder! {
|
event_builder! {
|
||||||
MouseEvent;
|
MouseEvent;
|
||||||
click contextmenu doubleclick drag dragend dragenter dragexit
|
click contextmenu doubleclick drag dragend dragenter dragexit
|
||||||
|
|
|
@ -138,6 +138,8 @@ pub mod prelude {
|
||||||
use crate::nodes;
|
use crate::nodes;
|
||||||
pub use nodes::*;
|
pub use nodes::*;
|
||||||
|
|
||||||
|
pub use crate::nodebuilder::LazyNodes;
|
||||||
|
|
||||||
pub use crate::context::NodeCtx;
|
pub use crate::context::NodeCtx;
|
||||||
// pub use nodes::iterables::IterableNodes;
|
// pub use nodes::iterables::IterableNodes;
|
||||||
/// This type alias is an internal way of abstracting over the static functions that represent components.
|
/// This type alias is an internal way of abstracting over the static functions that represent components.
|
||||||
|
|
|
@ -16,14 +16,13 @@ use crate::{
|
||||||
/// function for building `<div>` elements or the `button` function for building
|
/// function for building `<div>` elements or the `button` function for building
|
||||||
/// `<button>` elements.
|
/// `<button>` elements.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ElementBuilder<'a, Listeners, Attributes, Children>
|
pub struct ElementBuilder<'a, 'b, Listeners, Attributes, Children>
|
||||||
where
|
where
|
||||||
Listeners: 'a + AsRef<[Listener<'a>]>,
|
Listeners: 'a + AsRef<[Listener<'a>]>,
|
||||||
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
||||||
Children: 'a + AsRef<[VNode<'a>]>,
|
Children: 'a + AsRef<[VNode<'a>]>,
|
||||||
{
|
{
|
||||||
ctx: NodeCtx<'a>,
|
ctx: &'b NodeCtx<'a>,
|
||||||
// ctx: &'b NodeCtx<'a>,
|
|
||||||
key: NodeKey,
|
key: NodeKey,
|
||||||
tag_name: &'a str,
|
tag_name: &'a str,
|
||||||
listeners: Listeners,
|
listeners: Listeners,
|
||||||
|
@ -32,9 +31,10 @@ where
|
||||||
namespace: Option<&'a str>,
|
namespace: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a>
|
impl<'a, 'b>
|
||||||
ElementBuilder<
|
ElementBuilder<
|
||||||
'a,
|
'a,
|
||||||
|
'b,
|
||||||
bumpalo::collections::Vec<'a, Listener<'a>>,
|
bumpalo::collections::Vec<'a, Listener<'a>>,
|
||||||
bumpalo::collections::Vec<'a, Attribute<'a>>,
|
bumpalo::collections::Vec<'a, Attribute<'a>>,
|
||||||
bumpalo::collections::Vec<'a, VNode<'a>>,
|
bumpalo::collections::Vec<'a, VNode<'a>>,
|
||||||
|
@ -63,24 +63,22 @@ impl<'a>
|
||||||
/// let my_element_builder = ElementBuilder::new(&b, tag_name);
|
/// let my_element_builder = ElementBuilder::new(&b, tag_name);
|
||||||
/// # fn flip_coin() -> bool { true }
|
/// # fn flip_coin() -> bool { true }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(ctx: &NodeCtx<'a>, tag_name: &'static str) -> Self {
|
pub fn new(ctx: &'b NodeCtx<'a>, tag_name: &'static str) -> Self {
|
||||||
// pub fn new(ctx: &'b NodeCtx<'a>, tag_name: &'static str) -> Self {
|
|
||||||
// pub fn new<B>(ctx: &'a mut NodeCtx<'a>, tag_name: &'a str) -> Self {
|
|
||||||
let bump = ctx.bump;
|
let bump = ctx.bump;
|
||||||
todo!()
|
ElementBuilder {
|
||||||
// ElementBuilder {
|
ctx,
|
||||||
// ctx,
|
key: NodeKey::NONE,
|
||||||
// key: NodeKey::NONE,
|
tag_name,
|
||||||
// tag_name,
|
listeners: bumpalo::collections::Vec::new_in(bump),
|
||||||
// listeners: bumpalo::collections::Vec::new_in(bump),
|
attributes: bumpalo::collections::Vec::new_in(bump),
|
||||||
// attributes: bumpalo::collections::Vec::new_in(bump),
|
children: bumpalo::collections::Vec::new_in(bump),
|
||||||
// children: bumpalo::collections::Vec::new_in(bump),
|
namespace: None,
|
||||||
// namespace: None,
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Listeners, Attributes, Children> ElementBuilder<'a, Listeners, Attributes, Children>
|
impl<'a, 'b, Listeners, Attributes, Children>
|
||||||
|
ElementBuilder<'a, 'b, Listeners, Attributes, Children>
|
||||||
where
|
where
|
||||||
Listeners: 'a + AsRef<[Listener<'a>]>,
|
Listeners: 'a + AsRef<[Listener<'a>]>,
|
||||||
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
||||||
|
@ -114,7 +112,7 @@ where
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn listeners<L>(self, listeners: L) -> ElementBuilder<'a, L, Attributes, Children>
|
pub fn listeners<L>(self, listeners: L) -> ElementBuilder<'a, 'b, L, Attributes, Children>
|
||||||
where
|
where
|
||||||
L: 'a + AsRef<[Listener<'a>]>,
|
L: 'a + AsRef<[Listener<'a>]>,
|
||||||
{
|
{
|
||||||
|
@ -153,7 +151,7 @@ where
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn attributes<A>(self, attributes: A) -> ElementBuilder<'a, Listeners, A, Children>
|
pub fn attributes<A>(self, attributes: A) -> ElementBuilder<'a, 'b, Listeners, A, Children>
|
||||||
where
|
where
|
||||||
A: 'a + AsRef<[Attribute<'a>]>,
|
A: 'a + AsRef<[Attribute<'a>]>,
|
||||||
{
|
{
|
||||||
|
@ -192,7 +190,7 @@ where
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn children<C>(self, children: C) -> ElementBuilder<'a, Listeners, Attributes, C>
|
pub fn children<C>(self, children: C) -> ElementBuilder<'a, 'b, Listeners, Attributes, C>
|
||||||
where
|
where
|
||||||
C: 'a + AsRef<[VNode<'a>]>,
|
C: 'a + AsRef<[VNode<'a>]>,
|
||||||
{
|
{
|
||||||
|
@ -311,8 +309,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Attributes, Children>
|
impl<'a, 'b, Attributes, Children>
|
||||||
ElementBuilder<'a, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children>
|
ElementBuilder<'a, 'b, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children>
|
||||||
where
|
where
|
||||||
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
||||||
Children: 'a + AsRef<[VNode<'a>]>,
|
Children: 'a + AsRef<[VNode<'a>]>,
|
||||||
|
@ -365,8 +363,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Listeners, Children>
|
impl<'a, 'b, Listeners, Children>
|
||||||
ElementBuilder<'a, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children>
|
ElementBuilder<'a, 'b, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children>
|
||||||
where
|
where
|
||||||
Listeners: 'a + AsRef<[Listener<'a>]>,
|
Listeners: 'a + AsRef<[Listener<'a>]>,
|
||||||
Children: 'a + AsRef<[VNode<'a>]>,
|
Children: 'a + AsRef<[VNode<'a>]>,
|
||||||
|
@ -424,8 +422,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Listeners, Attributes>
|
impl<'a, 'b, Listeners, Attributes>
|
||||||
ElementBuilder<'a, Listeners, Attributes, bumpalo::collections::Vec<'a, VNode<'a>>>
|
ElementBuilder<'a, 'b, Listeners, Attributes, bumpalo::collections::Vec<'a, VNode<'a>>>
|
||||||
where
|
where
|
||||||
Listeners: 'a + AsRef<[Listener<'a>]>,
|
Listeners: 'a + AsRef<[Listener<'a>]>,
|
||||||
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
||||||
|
@ -451,16 +449,26 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_child(mut self, nodes: impl IntoIterator<Item = DomTree>) -> Self {
|
/// Add multiple children to this element from an iterator.
|
||||||
for item in nodes.into_iter() {
|
///
|
||||||
self.children.push(item.root);
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use dioxus::{builder::*, bumpalo::Bump};
|
||||||
|
///
|
||||||
|
/// let b = Bump::new();
|
||||||
|
///
|
||||||
|
/// let my_div = p(&b)
|
||||||
|
/// .iter_child((0..10).map(|f| span(&b).finish())
|
||||||
|
/// .finish();
|
||||||
|
/// ```
|
||||||
|
pub fn iter_child(mut self, nodes: impl IntoIterator<Item = impl IntoDomTree<'a>>) -> Self {
|
||||||
|
for item in nodes {
|
||||||
|
let child = item.into_vnode(&self.ctx);
|
||||||
|
self.children.push(child);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_tomdtree(mut self, nodes: impl IntoDomTree<'a>) -> Self {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoIterator for DomTree {
|
impl IntoIterator for DomTree {
|
||||||
|
@ -472,166 +480,124 @@ impl IntoIterator for DomTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoDomTree<'a> {
|
pub trait IntoDomTree<'a> {
|
||||||
type NodeIter: IntoIterator<Item = DomTree>;
|
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a>;
|
||||||
fn into_domtree(self, ctx: &NodeCtx<'a>) -> Self::NodeIter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoDomTree<'_> for DomTree {
|
// Cover the cases where nodes are pre-rendered.
|
||||||
type NodeIter = std::iter::Once<DomTree>;
|
// Likely used by enums.
|
||||||
fn into_domtree(self, ctx: &NodeCtx) -> Self::NodeIter {
|
// ----
|
||||||
std::iter::once(self)
|
// let nodes = ctx.render(rsx!{ ... };
|
||||||
|
// rsx! { {nodes } }
|
||||||
|
impl<'a> IntoDomTree<'a> for DomTree {
|
||||||
|
fn into_vnode(self, _ctx: &NodeCtx<'a>) -> VNode<'a> {
|
||||||
|
self.root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, G> IntoDomTree<'a> for NodeWrapper<'a, G>
|
// Wrap the the node-builder closure in a concrete type.
|
||||||
|
// ---
|
||||||
|
// This is a bit of a hack to implement the IntoDomTree trait for closure types.
|
||||||
|
pub struct LazyNodes<'a, G>
|
||||||
where
|
where
|
||||||
G: for<'b, 'c> FnOnce(&'b NodeCtx<'c>) -> VNode<'c> + 'a,
|
G: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a,
|
||||||
{
|
|
||||||
type NodeIter = std::iter::Once<DomTree>;
|
|
||||||
|
|
||||||
fn into_domtree(self, ctx: &NodeCtx) -> Self::NodeIter {
|
|
||||||
let p: VNode<'_> = (self.inner)(ctx);
|
|
||||||
let root: VNode<'static> = unsafe { std::mem::transmute(p) };
|
|
||||||
std::iter::once(DomTree { root })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, G, I> IntoDomTree<'a> for I
|
|
||||||
where
|
|
||||||
G: for<'b, 'c> FnOnce(&'b NodeCtx<'c>) -> VNode<'c> + 'a,
|
|
||||||
I: Iterator<Item = NodeWrapper<'a, G>>,
|
|
||||||
// O: Iterator<Item = DomTree>,
|
|
||||||
{
|
|
||||||
type NodeIter = std::iter::Map<I, O>;
|
|
||||||
|
|
||||||
fn into_domtree(self, ctx: &NodeCtx) -> Self::NodeIter {
|
|
||||||
self.map(|f| {
|
|
||||||
//
|
|
||||||
let caller = (f.inner);
|
|
||||||
let r = caller(ctx);
|
|
||||||
})
|
|
||||||
// todo!()
|
|
||||||
// let p: VNode<'_> = (self.inner)(ctx);
|
|
||||||
// let root: VNode<'static> = unsafe { std::mem::transmute(p) };
|
|
||||||
// std::iter::once(DomTree { root })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
all possible impls
|
|
||||||
|
|
||||||
rsx!{ }
|
|
||||||
ctx.render(rsx!)
|
|
||||||
|
|
||||||
map(rsx!)
|
|
||||||
map(ctx.render(rsx!))
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub struct NodeWrapper<'a, G>
|
|
||||||
where
|
|
||||||
G: for<'b, 'c> FnOnce(&'b NodeCtx<'c>) -> VNode<'c> + 'a,
|
|
||||||
{
|
{
|
||||||
inner: G,
|
inner: G,
|
||||||
_p: std::marker::PhantomData<&'a ()>,
|
_p: std::marker::PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_wrapper<'a, G>(f: G) -> NodeWrapper<'a, G>
|
impl<'a, G> LazyNodes<'a, G>
|
||||||
|
where
|
||||||
|
G: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a,
|
||||||
|
{
|
||||||
|
pub fn new(f: G) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: f,
|
||||||
|
_p: std::default::Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cover the cases where nodes are used by macro.
|
||||||
|
// Likely used directly.
|
||||||
|
// ---
|
||||||
|
// let nodes = rsx!{ ... };
|
||||||
|
// rsx! { {nodes } }
|
||||||
|
impl<'a, G> IntoDomTree<'a> for LazyNodes<'a, G>
|
||||||
|
where
|
||||||
|
G: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a,
|
||||||
|
{
|
||||||
|
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
|
||||||
|
(self.inner)(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required because anything that enters brackets in the rsx! macro needs to implement IntoIterator
|
||||||
|
impl<'a, G> IntoIterator for LazyNodes<'a, G>
|
||||||
where
|
where
|
||||||
G: for<'b, 'c> FnOnce(&'b NodeCtx<'c>) -> VNode<'c> + 'a,
|
G: for<'b, 'c> FnOnce(&'b NodeCtx<'c>) -> VNode<'c> + 'a,
|
||||||
{
|
{
|
||||||
NodeWrapper {
|
type Item = Self;
|
||||||
inner: f,
|
type IntoIter = std::iter::Once<Self::Item>;
|
||||||
_p: std::default::Default::default(),
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
std::iter::once(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_of_nodes<'b>() {
|
fn test_iterator_of_nodes<'b>() {
|
||||||
let p = (0..10).map(|f| {
|
use crate::prelude::*;
|
||||||
//
|
|
||||||
new_wrapper(rsx! {
|
|
||||||
div {
|
|
||||||
"aaa {f}"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
let g = p.into_iter();
|
|
||||||
for f in g {}
|
|
||||||
|
|
||||||
static Example: FC<()> = |ctx, props| {
|
static Example: FC<()> = |ctx, props| {
|
||||||
ctx.render(|c| {
|
let g: LazyNodes<_> = rsx! {
|
||||||
//
|
|
||||||
ElementBuilder::new(c, "div")
|
|
||||||
.into_tomdtree({
|
|
||||||
// rsx!
|
|
||||||
new_wrapper(move |n: &NodeCtx| -> VNode {
|
|
||||||
//
|
|
||||||
ElementBuilder::new(n, "div").finish()
|
|
||||||
})
|
|
||||||
// use the macro to be "blind" to the type
|
|
||||||
// everything gets interpreted as
|
|
||||||
/*
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for node in {expr} {
|
|
||||||
ctx.push_alloc_node(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
so.... just make sure whatever enters {} is iterable (domtree and nodewrapper need impls, )
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
})
|
|
||||||
.into_tomdtree({
|
|
||||||
// render to wrapper -> tree
|
|
||||||
ctx.render(rsx! {
|
|
||||||
div {}
|
div {}
|
||||||
})
|
};
|
||||||
})
|
|
||||||
.into_tomdtree({
|
ctx.render(rsx! {
|
||||||
// map rsx!
|
div {
|
||||||
(0..10).map(|f| {
|
h1 {}
|
||||||
new_wrapper(move |n: &NodeCtx| -> VNode {
|
{}
|
||||||
//
|
}
|
||||||
ElementBuilder::new(n, "div").finish()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finish()
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::prelude::*;
|
// let p = (0..10).map(|f| {
|
||||||
|
|
||||||
// static Example: FC<()> = |ctx, props| {
|
|
||||||
// //
|
// //
|
||||||
// let list = (0..10).map(|f| {
|
// LazyNodes::new(rsx! {
|
||||||
// ctx.render(rsx! {
|
// div {
|
||||||
// div {}
|
// "aaa {f}"
|
||||||
|
// }
|
||||||
// })
|
// })
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
// let g = p.into_iter();
|
||||||
|
// for f in g {}
|
||||||
|
|
||||||
|
// static Example: FC<()> = |ctx, props| {
|
||||||
// ctx.render(|c| {
|
// ctx.render(|c| {
|
||||||
|
// //
|
||||||
// ElementBuilder::new(c, "div")
|
// ElementBuilder::new(c, "div")
|
||||||
// .iter_child({
|
// .iter_child({
|
||||||
|
// // rsx!
|
||||||
|
// LazyNodes::new(move |n: &NodeCtx| -> VNode {
|
||||||
// //
|
// //
|
||||||
|
// ElementBuilder::new(n, "div").finish()
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .iter_child({
|
||||||
|
// // render to wrapper -> tree
|
||||||
// ctx.render(rsx! {
|
// ctx.render(rsx! {
|
||||||
// div {}
|
// div {}
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
// .iter_child({
|
// .iter_child({
|
||||||
// //
|
// // map rsx!
|
||||||
// (0..10).map(|f| {
|
// (0..10).map(|f| {
|
||||||
// ctx.render(rsx! {
|
// LazyNodes::new(move |n: &NodeCtx| -> VNode {
|
||||||
// div {}
|
// //
|
||||||
|
// ElementBuilder::new(n, "div").finish()
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
// .iter_child(list)
|
|
||||||
// .finish()
|
// .finish()
|
||||||
// })
|
// })
|
||||||
// };
|
// };
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
events::VirtualEvent,
|
events::VirtualEvent,
|
||||||
innerlude::{Context, Properties, ScopeIdx, FC},
|
innerlude::{Context, NodeCtx, Properties, ScopeIdx, FC},
|
||||||
};
|
};
|
||||||
|
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
|
10
packages/docsite/Cargo.toml
Normal file
10
packages/docsite/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "dioxus-docs-site"
|
||||||
|
version = "0.0.0"
|
||||||
|
authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dioxus-ssr = { path = "../ssr" }
|
10
packages/docsite/README.md
Normal file
10
packages/docsite/README.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Dioxus docs site
|
||||||
|
|
||||||
|
Generate the liveview site powering diouxslabs.com.
|
||||||
|
|
||||||
|
We use the dioxus SSR crate and the use_router hook to generate a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
0
packages/docsite/src/components/app.rs
Normal file
0
packages/docsite/src/components/app.rs
Normal file
82
packages/docsite/src/main.rs
Normal file
82
packages/docsite/src/main.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
use dioxus_ssr::{prelude::*, TextRenderer};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
TextRenderer::new(App);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum Routes {
|
||||||
|
Homepage,
|
||||||
|
ExampleList,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Props)]
|
||||||
|
struct AppProps {
|
||||||
|
route: Routes,
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Blah {}
|
||||||
|
impl<'a, G> Blah for LazyNodes<'a, G> where G: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a {}
|
||||||
|
|
||||||
|
static App: FC<AppProps> = |ctx, props| {
|
||||||
|
//
|
||||||
|
let body = match props.route {
|
||||||
|
Routes::Homepage => ctx.render(rsx!(
|
||||||
|
div {
|
||||||
|
Homepage {}
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
Routes::ExampleList => ctx.render(rsx!(
|
||||||
|
div {
|
||||||
|
ExampleList {}
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.render(rsx!(
|
||||||
|
div {
|
||||||
|
Header {}
|
||||||
|
{body}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Footer {}
|
||||||
|
}
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Props)]
|
||||||
|
struct HeaderProp {
|
||||||
|
selected: Routes,
|
||||||
|
}
|
||||||
|
|
||||||
|
static Header: FC<()> = |ctx, _| {
|
||||||
|
ctx.render(rsx! {
|
||||||
|
div {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
static Footer: FC<()> = |ctx, _| {
|
||||||
|
ctx.render(rsx! {
|
||||||
|
div {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
static Homepage: FC<()> = |ctx, _| {
|
||||||
|
ctx.render(rsx! {
|
||||||
|
div {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
static ExampleList: FC<()> = |ctx, _| {
|
||||||
|
ctx.render(rsx! {
|
||||||
|
div {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
|
@ -21,6 +21,10 @@
|
||||||
|
|
||||||
use dioxus_core::prelude::{VNode, FC};
|
use dioxus_core::prelude::{VNode, FC};
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use dioxus_core::prelude::*;
|
||||||
|
}
|
||||||
|
|
||||||
/// The `TextRenderer` provides a way of rendering a Dioxus Virtual DOM to a String.
|
/// The `TextRenderer` provides a way of rendering a Dioxus Virtual DOM to a String.
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus::prelude::*;
|
use dioxus::{events::on::MouseEvent, prelude::*};
|
||||||
use dioxus_web::WebsysRenderer;
|
use dioxus_web::WebsysRenderer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -16,6 +16,9 @@ fn main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
#[derive(PartialEq, Props)]
|
||||||
struct ExampleProps {
|
struct ExampleProps {
|
||||||
initial_name: &'static str,
|
initial_name: &'static str,
|
||||||
|
@ -43,13 +46,14 @@ static Example: FC<ExampleProps> = |ctx, props| {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
struct ButtonProps<'src> {
|
struct ButtonProps<'src> {
|
||||||
name: &'src str,
|
name: &'src str,
|
||||||
set_name: &'src dyn Fn(String)
|
set_name: &'src dyn Fn(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// this is an awesome component
|
|
||||||
fn CustomButton<'a>(ctx: Context<'a>, props: &'a ButtonProps<'a>) -> DomTree {
|
fn CustomButton<'a>(ctx: Context<'a>, props: &'a ButtonProps<'a>) -> DomTree {
|
||||||
ctx.render(rsx!{
|
ctx.render(rsx!{
|
||||||
button {
|
button {
|
||||||
|
|
Loading…
Reference in a new issue