diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index 18005fa59..c6da580d8 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -3,6 +3,9 @@ name = "dioxus-core" version = "0.1.0" authors = ["Jonathan Kelley "] edition = "2018" +description = "Core functionality for Dioxus - a concurrent renderer-agnostic Virtual DOM for interactive user experiences" +"license" = "MIT/Apache-2.0" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/packages/core/examples/simple.rs b/packages/core/examples/simple.rs index 5ace935c8..73b2a7a0a 100644 --- a/packages/core/examples/simple.rs +++ b/packages/core/examples/simple.rs @@ -1,6 +1,6 @@ use std::future::Future; -use dioxus_core::{component::AnyContext, prelude::*}; +use dioxus_core::prelude::*; // use virtual_dom_rs::Closure; // Stop-gap while developing @@ -8,12 +8,16 @@ use dioxus_core::{component::AnyContext, prelude::*}; type VirtualNode = VNode; pub fn main() { - let dom = VirtualDom::new(root); + let dom = VirtualDom::new_with_props(root); // let mut renderer = TextRenderer::new(dom); // let output = renderer.render(); } -fn root(ctx: &mut AnyContext) -> VNode { +struct Props { + name: String, +} + +fn root(ctx: &mut Context) -> VNode { // the regular html syntax // html! { @@ -61,15 +65,15 @@ fn root(ctx: &mut AnyContext) -> VNode { } } -fn Head(ctx: &mut AnyContext) -> VNode { +fn Head(ctx: &mut Context) -> VNode { html! { - {"Head Section"} + "Head Section" } } -fn Body(ctx: &mut AnyContext) -> VNode { +fn Body(ctx: &mut Context) -> VNode { html! { {"Footer Section"} @@ -77,10 +81,18 @@ fn Body(ctx: &mut AnyContext) -> VNode { } } -fn Footer(ctx: &mut AnyContext) -> VNode { +fn Footer(ctx: &mut Context) -> VNode { + let mut v = 10_i32; + format!("Is this the real life, or is this fantasy, caught in a landslide"); + html! {
- {"Footer Section"} + "Footer Section" + "Footer Section" + "Footer Section" + "Footer Section" + "Footer Section" + "Footer Section"
} } diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 1182d5bed..a9b647fdd 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -8,9 +8,8 @@ /// /// pub mod prelude { - pub use crate::component::Context; use crate::nodes; - pub use crate::types::FC; + pub use crate::virtual_dom::Context; pub use crate::virtual_dom::VirtualDom; pub use nodes::iterables::IterableNodes; pub use nodes::*; @@ -24,20 +23,76 @@ pub mod prelude { /// The Dioxus Virtual Dom integrates an event system and virtual nodes to create reactive user interfaces. /// -/// +/// This module includes all life-cycle related mechanics, including the virtual dom, scopes, properties, and lifecycles. /// pub mod virtual_dom { use super::*; + use crate::nodes::VNode; + use generational_arena::Arena; /// An integrated virtual node system that progresses events and diffs UI trees. /// Differences are converted into patches which a renderer can use to draw the UI. - pub struct VirtualDom {} + pub struct VirtualDom { + arena: Arena, + } impl VirtualDom { - pub fn new(root: types::FC) -> Self { + /// Create a new instance of the Dioxus Virtual Dom with no properties for the root component. + /// + /// This means that the root component must either consumes its own context, or statics are used to generate the page. + /// The root component can access things like routing in its context. + pub fn new(root: FC<()>) -> Self { + Self::new_with_props(root) + } + + /// Start a new VirtualDom instance with a dependent props. + /// Later, the props can be updated by calling "update" with a new set of props, causing a set of re-renders. + /// + /// This is useful when a component tree can be driven by external state (IE SSR) but it would be too expensive + /// to toss out the entire tree. + pub fn new_with_props(root: FC) -> Self { + Self { + arena: Arena::new(), + } + } + } + + /// Functional Components leverage the type FC to + pub type FC = fn(&mut Context) -> VNode; + + /// The Scope that wraps a functional component + /// Scope's hold subscription, context, and hook information, however, it is allocated on the heap. + pub struct Scope {} + + impl Scope { + fn new() -> Self { Self {} } } + + /// Components in Dioxus use the "Context" object to interact with their lifecycle. + /// This lets components schedule updates, integrate hooks, and expose their context via the context api. + /// + /// Properties passed down from the parent component are also directly accessible via the exposed "props" field. + /// + /// ```ignore + /// #[derive(Properties)] + /// struct Props { + /// name: String + /// } + /// + /// fn example(ctx: &Context) -> VNode { + /// html! { + ///
"Hello, {ctx.props.name}"
+ /// } + /// } + /// ``` + pub struct Context<'source, T> { + _props: std::marker::PhantomData<&'source T>, + } + + pub trait Properties {} + impl Properties for () {} } /// Virtual Node Support @@ -628,7 +683,7 @@ pub mod diff { /// Given two VNode's generate Patch's that would turn the old virtual node's /// real DOM node equivalent into the new VNode's real DOM node equivalent. - pub fn diff<'a>(old: &'a VNode, new: &'a VNode) -> Vec> { + pub fn diff_vnodes<'a>(old: &'a VNode, new: &'a VNode) -> Vec> { diff_recursive(&old, &new, &mut 0) } @@ -641,6 +696,8 @@ pub mod diff { let mut replace = false; // Different enum variants, replace! + // VNodes are of different types, and therefore will cause a re-render. + // TODO: Handle previously-mounted children so they don't get re-mounted if mem::discriminant(old) != mem::discriminant(new) { replace = true; } @@ -794,7 +851,7 @@ pub mod diff { impl<'a> DiffTestCase<'a> { pub fn test(&self) { // ex: vec![Patch::Replace(0, &html! { })], - let patches = diff(&self.old, &self.new); + let patches = diff_vnodes(&self.old, &self.new); assert_eq!(patches, self.expected, "{}", self.description); } @@ -992,37 +1049,6 @@ pub mod diff { } } -/// -/// -/// -/// -/// -pub mod component { - - /// A wrapper around component contexts that hides component property types - pub struct AnyContext {} - pub struct Context { - _props: std::marker::PhantomData, - } - - pub trait Properties {} - impl Properties for () {} - - fn test() {} -} - -/// Utility types that wrap internals -/// -/// -/// -pub mod types { - use super::*; - use component::{AnyContext, Context}; - use nodes::VNode; - - pub type FC = fn(&mut AnyContext) -> VNode; -} - /// TODO @Jon /// Figure out if validation should be its own crate, or embedded directly into dioxus /// Should we even be bothered with validation?