From 7cfacfc78e0c003e8b2bf0c51f625f0f79b5d793 Mon Sep 17 00:00:00 2001 From: Emmanuel Surleau Date: Sat, 16 Sep 2023 19:27:39 +0200 Subject: [PATCH] Bump leptos dependency to 0.5. --- Cargo.toml | 2 +- src/async_.rs | 2 +- src/if_.rs | 348 ++++++++++++++++++++++++-------------------------- src/lib.rs | 21 ++- src/portal.rs | 163 +++++++++++------------ src/when.rs | 8 +- 6 files changed, 261 insertions(+), 283 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a374ed4..7b7ea3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,4 @@ keywords = ["leptos", "web", "framework", "reactive", "isomorphic"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -leptos = "0.3" \ No newline at end of file +leptos = { version = "0.5.0-rc1", features = ["csr"] } diff --git a/src/async_.rs b/src/async_.rs index 53d8f3c..98aa707 100644 --- a/src/async_.rs +++ b/src/async_.rs @@ -1,5 +1,5 @@ api_planning! { - view! { cx, + view! { diff --git a/src/if_.rs b/src/if_.rs index bc4767a..413c140 100644 --- a/src/if_.rs +++ b/src/if_.rs @@ -7,7 +7,7 @@ use leptos_dom::Transparent; use std::cell::Cell; api_planning! { - view! { cx, + view! { "thing to show if bool_signal is true" @@ -36,15 +36,15 @@ api_planning! { /// use leptos::*; /// use leptos_declarative::prelude::*; /// -/// # let _ = create_scope(create_runtime(), |cx| { -/// let (a, _) = create_signal(cx, true); +/// # let runtime = create_runtime(); +/// let (a, _) = create_signal(true); /// -/// view! { cx, +/// view! { /// /// "a is true!" /// /// }; -/// # }); +/// # runtime.dispose(); /// ``` /// /// ### `if/else` @@ -52,16 +52,16 @@ api_planning! { /// use leptos::*; /// use leptos_declarative::prelude::*; /// -/// # let _ = create_scope(create_runtime(), |cx| { -/// let (a, _) = create_signal(cx, true); +/// # let runtime = create_runtime(); +/// let (a, _) = create_signal(true); /// -/// view! { cx, +/// view! { /// /// "A is true!" /// "A is false!" /// /// }; -/// # }); +/// # runtime.dispose(); /// ``` /// /// ### `if/else-if` @@ -69,18 +69,18 @@ api_planning! { /// use leptos::*; /// use leptos_declarative::prelude::*; /// -/// # let _ = create_scope(create_runtime(), |cx| { -/// let (a, _) = create_signal(cx, true); -/// let (b, _) = create_signal(cx, false); +/// # let runtime = create_runtime(); +/// let (a, _) = create_signal(true); +/// let (b, _) = create_signal(false); /// -/// view! { cx, +/// view! { /// /// "A is true!" /// "B is true!" /// "Both A and B are false!" /// /// }; -/// # }); +/// # runtime.dispose(); /// ``` /// /// ### `MaybeSignal` @@ -94,110 +94,104 @@ api_planning! { /// use leptos::*; /// use leptos_declarative::prelude::*; /// -/// # let _ = create_scope(create_runtime(), |cx| { +/// # let runtime = create_runtime(); /// -/// view! { cx, +/// view! { /// /// "a is true!" /// "b is true!" /// /// }; -/// # }); +/// # runtime.dispose(); /// ``` #[component] pub fn If( - cx: Scope, - /// The bool signal. - #[prop(into)] - signal: MaybeSignal, - /// The `if` conditions you would like to evaluate. - /// - /// Children must be any - /// - [`Then`] - /// - [`ElseIf`] - /// - [`Else`] - /// - /// Any other child not in the above list will not be rendered. - /// - /// [`Then`] must be present and the first child. - /// - /// [`Else`] must be the last child. - children: Box Fragment>, + /// The bool signal. + #[prop(into)] + signal: MaybeSignal, + /// The `if` conditions you would like to evaluate. + /// + /// Children must be any + /// - [`Then`] + /// - [`ElseIf`] + /// - [`Else`] + /// + /// Any other child not in the above list will not be rendered. + /// + /// [`Then`] must be present and the first child. + /// + /// [`Else`] must be the last child. + children: Box Fragment>, ) -> impl IntoView { - // Memoize the signal - let signal = create_memo(cx, move |_| signal.get()); - - let children = children(cx); - - // Get the condition blocks - let if_blocks = children - .as_children() - .iter() - .filter_map(View::as_transparent) - .cloned() - .collect::>(); - - #[cfg(debug_assertions)] - run_debug_checks(&if_blocks); - - let last_rendered_block = Cell::>::new(None); - let child = Cell::new(().into_view(cx)); - - move || { - let mut if_blocks = if_blocks - .iter() - .filter_map(Transparent::downcast_ref::) - .enumerate(); - - // Subscribe all blocks - if_blocks.clone().skip(1).for_each(|(_, block)| { - if let IfBlock::ElseIf { signal, .. } = block { - signal.track(); - } - }); - - if signal.get() { - if last_rendered_block.get() != Some(0) { - last_rendered_block.set(Some(0)); - - let new_child = if_blocks.next().unwrap().1.render(cx).into_view(cx); - - child.set(new_child); - } - } else if let Some((i, block)) = - if_blocks.find(|(_, block)| block.is_true()) - { - if last_rendered_block.get() != Some(i) { - last_rendered_block.set(Some(i)); - - let new_child = block.render(cx).into_view(cx); - - child.set(new_child); - } - } else { - last_rendered_block.set(None); - - child.set(().into_view(cx)); - } + // Memoize the signal + let signal = create_memo(move |_| signal.get()); - let view = child.take(); - child.set(view.clone()); + let children = children(); - view - } + // Get the condition blocks + let if_blocks = children + .as_children() + .iter() + .filter_map(View::as_transparent) + .cloned() + .collect::>(); + + #[cfg(debug_assertions)] + run_debug_checks(&if_blocks); + + let last_rendered_block = Cell::>::new(None); + let child = Cell::new(().into_view()); + + move || { + let mut if_blocks = if_blocks + .iter() + .filter_map(Transparent::downcast_ref::) + .enumerate(); + + // Subscribe all blocks + if_blocks.clone().skip(1).for_each(|(_, block)| { + if let IfBlock::ElseIf { signal, .. } = block { + signal.track(); + } + }); + + if signal.get() { + if last_rendered_block.get() != Some(0) { + last_rendered_block.set(Some(0)); + + let new_child = if_blocks.next().unwrap().1.render().into_view(); + + child.set(new_child); + } + } else if let Some((i, block)) = if_blocks.find(|(_, block)| block.is_true()) { + if last_rendered_block.get() != Some(i) { + last_rendered_block.set(Some(i)); + + let new_child = block.render().into_view(); + + child.set(new_child); + } + } else { + last_rendered_block.set(None); + + child.set(().into_view()); + } + + let view = child.take(); + child.set(view.clone()); + + view + } } /// This must be the first direct child of [`If`]. It will be shown /// iff the signal provided to [`If`] is true. #[component(transparent)] pub fn Then( - cx: Scope, - /// What you want to show when this `if` expression is evaluated. - children: Box Fragment>, + /// What you want to show when this `if` expression is evaluated. + children: Box Fragment>, ) -> impl IntoView { - let _ = cx; - - IfBlock::If { children } + IfBlock::If { children } } /// This must be the direct child of an [`If`] component, and be placed after @@ -205,116 +199,112 @@ pub fn Then( /// is false and all other [`ElseIf`] signals are false and this one is true. #[component(transparent)] pub fn ElseIf( - cx: Scope, - /// The bool signal. - #[prop(into)] - signal: MaybeSignal, - /// What you want to show when this `else if` expression is evaluated. - children: Box Fragment>, + /// The bool signal. + #[prop(into)] + signal: MaybeSignal, + /// What you want to show when this `else if` expression is evaluated. + children: Box Fragment>, ) -> impl IntoView { - let signal = create_memo(cx, move |_| signal.get()); + let signal = create_memo(move |_| signal.get()); - IfBlock::ElseIf { signal, children } + IfBlock::ElseIf { signal, children } } /// This must be the direct child of an [`If`] component, and be the last component. /// It will render it's children iff all other signals are false. #[component(transparent)] pub fn Else( - cx: Scope, - /// What you want to show when all other signals are false. - children: Box Fragment>, + /// What you want to show when all other signals are false. + children: Box Fragment>, ) -> impl IntoView { - let _ = cx; - - IfBlock::Else { children } + IfBlock::Else { children } } /// Represents an if block which is returned by [`Then`], [`ElseIf`] /// or [`Else`] components. pub enum IfBlock { - /// The initial `if` condition, returned by [`Then`]. - If { - /// The children method. - children: Box Fragment>, - }, - /// An `else if` condition, returned by [`ElseIf`]. - ElseIf { - /// The signal which must evaluate to true to be rendered. - signal: Memo, - /// The children method. - children: Box Fragment>, - }, - /// The `else` condition, returned by [`Else`]. - Else { - /// The children method. - children: Box Fragment>, - }, + /// The initial `if` condition, returned by [`Then`]. + If { + /// The children method. + children: Box Fragment>, + }, + /// An `else if` condition, returned by [`ElseIf`]. + ElseIf { + /// The signal which must evaluate to true to be rendered. + signal: Memo, + /// The children method. + children: Box Fragment>, + }, + /// The `else` condition, returned by [`Else`]. + Else { + /// The children method. + children: Box Fragment>, + }, } impl IfBlock { - fn is_true(&self) -> bool { - if let Self::ElseIf { signal, .. } = self { - signal.get() - } else { - self.is_else() + fn is_true(&self) -> bool { + if let Self::ElseIf { signal, .. } = self { + signal.get() + } else { + self.is_else() + } } - } - fn is_if(&self) -> bool { - matches!(self, Self::If { .. }) - } + fn is_if(&self) -> bool { + matches!(self, Self::If { .. }) + } - fn is_else(&self) -> bool { - matches!(self, Self::Else { .. }) - } + fn is_else(&self) -> bool { + matches!(self, Self::Else { .. }) + } - fn render(&self, cx: Scope) -> Fragment { - match self { - Self::If { children } => children(cx), - Self::ElseIf { children, .. } => children(cx), - Self::Else { children } => children(cx), + fn render(&self) -> Fragment { + match self { + Self::If { children } => children(), + Self::ElseIf { children, .. } => children(), + Self::Else { children } => children(), + } } - } } impl IntoView for IfBlock { - fn into_view(self, _: Scope) -> View { - View::Transparent(Transparent::new(self)) - } + fn into_view(self) -> View { + View::Transparent(Transparent::new(self)) + } } #[cfg(debug_assertions)] fn run_debug_checks(if_blocks: &[Transparent]) { - let if_blocks = if_blocks - .iter() - .filter_map(Transparent::downcast_ref::); - - // Make sure is first - assert!( - if_blocks.clone().next().unwrap().is_if(), - "`` must be the first child of ``" - ); - - // Make sure there is no more than 1 - assert_eq!( - if_blocks.clone().filter(|block| block.is_if()).count(), - 1, - "there must not be more than 1 `` children within ``" - ); - - // Make sure is last - if let Some(pos) = if_blocks.clone().position(|block| block.is_else()) { + let if_blocks = if_blocks + .iter() + .filter_map(Transparent::downcast_ref::); + + // Make sure is first + assert!( + if_blocks.clone().next().unwrap().is_if(), + "`` must be the first child of ``" + ); + + // Make sure there is no more than 1 assert_eq!( - pos, - if_blocks.clone().count() - 1, - "`` must be the last child of ``" + if_blocks.clone().filter(|block| block.is_if()).count(), + 1, + "there must not be more than 1 `` children within ``" ); - } - // Make sure there is no more than 1 - assert!( - if_blocks.filter(|block| block.is_else()).count() <= 1, - "there must not be more than 1 `` children within ``" - ); + // Make sure is last + if let Some(pos) = if_blocks.clone().position(|block| block.is_else()) { + assert_eq!( + pos, + if_blocks.clone().count() - 1, + "`` must be the last child of ``" + ); + } + + // Make sure there is no more than 1 + assert!( + if_blocks.filter(|block| block.is_else()).count() <= 1, + "there must not be more than 1 `` children within ``" + ); } diff --git a/src/lib.rs b/src/lib.rs index 7eb505a..14dec51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,18 +18,18 @@ //! use leptos::*; //! use leptos_declarative::prelude::*; //! -//! # let _ = create_scope(create_runtime(), |cx| { -//! let (a, _) = create_signal(cx, true); -//! let (b, _) = create_signal(cx, false); +//! # let runtime = create_runtime(); +//! let (a, _) = create_signal(true); +//! let (b, _) = create_signal(false); //! -//! view! { cx, +//! view! { //! //! "A is true!" //! "B is true!" //! "Both A and B are false!" //! //! }; -//! # }); +//! # runtime.dispose(); //! ``` //! //! ## Portal @@ -37,11 +37,11 @@ //! use leptos::*; //! use leptos_declarative::prelude::*; //! -//! # let _ = create_scope(create_runtime(), |cx| { +//! # let runtime = create_runtime(); //! //! struct PortalId; //! -//! view! { cx, +//! view! { //! //!
//!

"Portal goes here!"

@@ -53,7 +53,7 @@ //! //! //! }; -//! # }); +//! # runtime.dispose(); //! ``` #[macro_use] @@ -63,8 +63,5 @@ pub mod portal; /// Convenient import of all components. pub mod prelude { - pub use crate::{ - if_::*, - portal::*, - }; + pub use crate::{if_::*, portal::*}; } diff --git a/src/portal.rs b/src/portal.rs index e34585e..91c2124 100644 --- a/src/portal.rs +++ b/src/portal.rs @@ -6,31 +6,28 @@ //! For usage examples, please refer to [`PortalInput`]. use leptos::*; -use std::any::{ - Any, - TypeId, -}; +use std::any::{Any, TypeId}; api_planning! { struct PortalA; struct PortalB; // Somewhere up there - view! { cx, + view! { // rest of your app } // Where you want your portal to output - view! { cx, + view! {

"Where'd these come from???"

} // Where you want portal contents to go - view! { cx, + view! {

"I used a portal to get here..."

@@ -40,12 +37,11 @@ api_planning! { } } -const CONTEXT_NOT_FOUND_ERROR_MESSAGE: &str = - "failed to find `PortalCtx`, make sure you are using `` \ +const CONTEXT_NOT_FOUND_ERROR_MESSAGE: &str = "failed to find `PortalCtx`, make sure you are using `` \ somewhere near the root of the app"; #[derive(Clone)] -struct PortalCtx(StoredValue>)>>); +struct PortalCtx(StoredValue>)>>); /// The portal provider which allows to use [`PortalInput`] and [`PortalOutput`]. /// @@ -57,11 +53,11 @@ struct PortalCtx(StoredValue>)>>); /// use leptos::*; /// use leptos_declarative::prelude::*; /// -/// # let _ = create_scope(create_runtime(), |cx| { +/// # let runtime = create_runtime(); /// /// struct PortalId; /// -/// view! { cx, +/// view! { /// ///
///

"Portal goes here!"

@@ -73,18 +69,17 @@ struct PortalCtx(StoredValue>)>>); /// /// /// }; -/// # }); +/// # runtime.dispose(); /// ``` #[component] pub fn PortalProvider( - cx: Scope, - /// The rest of your app. [`PortalInput`] and [`PortalOutput`] can be used - /// anywhere below this point. - children: Children, + /// The rest of your app. [`PortalInput`] and [`PortalOutput`] can be used + /// anywhere below this point. + children: Children, ) -> impl IntoView { - provide_context(cx, PortalCtx(store_value(cx, Default::default()))); + provide_context(PortalCtx(store_value(Default::default()))); - children(cx) + children() } /// The portal entry point. Whatever children this component has will be rendered @@ -96,11 +91,11 @@ pub fn PortalProvider( /// use leptos::*; /// use leptos_declarative::prelude::*; /// -/// # let _ = create_scope(create_runtime(), |cx| { +/// # let runtime = create_runtime(); /// /// struct PortalId; /// -/// view! { cx, +/// view! { /// ///
///

"Portal goes here!"

@@ -112,36 +107,34 @@ pub fn PortalProvider( /// /// /// }; -/// # }); +/// # runtime.dispose(); /// ``` #[component] pub fn PortalInput( - cx: Scope, - /// The type used as an `id`. This must match the `id` of the - /// corresponding [`PortalOutput`]. - id: T, - /// The children you want to render anywhere the matching [`PortalOutput`] - /// is located. - children: Children, + /// The type used as an `id`. This must match the `id` of the + /// corresponding [`PortalOutput`]. + id: T, + /// The children you want to render anywhere the matching [`PortalOutput`] + /// is located. + children: ChildrenFn, ) -> impl IntoView where - T: Any, + T: Any, { - let portal_ctx = - use_context::(cx).expect(CONTEXT_NOT_FOUND_ERROR_MESSAGE); - - portal_ctx.0.update_value(|portals| { - if let Some(pos) = portals - .iter() - .position(|(type_id, _)| *type_id == id.type_id()) - { - portals[pos].1.set(Some(children)); - } else { - let children = create_rw_signal(cx, Some(children)); - - portals.push((id.type_id(), children)); - } - }); + let portal_ctx = use_context::().expect(CONTEXT_NOT_FOUND_ERROR_MESSAGE); + + portal_ctx.0.update_value(|portals| { + if let Some(pos) = portals + .iter() + .position(|(type_id, _)| *type_id == id.type_id()) + { + portals[pos].1.set(Some(children)); + } else { + let children = create_rw_signal(Some(children)); + + portals.push((id.type_id(), children)); + } + }); } /// The portal output point. Whatever children the corresponding [`Portal`} with @@ -152,11 +145,11 @@ where /// use leptos::*; /// use leptos_declarative::prelude::*; /// -/// # let _ = create_scope(create_runtime(), |cx| { +/// # let runtime = create_runtime(); /// /// struct PortalId; /// -/// view! { cx, +/// view! { /// ///
///

"Portal goes here!"

@@ -168,49 +161,47 @@ where /// /// /// }; -/// # }); +/// # runtime.dispose(); /// ``` #[component] pub fn PortalOutput( - cx: Scope, - /// The type used as an `id`. This must match the `id` of the - /// corresponding [`PortalInput`]. - id: T, + /// The type used as an `id`. This must match the `id` of the + /// corresponding [`PortalInput`]. + id: T, ) -> impl IntoView where - T: Any, + T: Any, { - let portal_ctx = - use_context::(cx).expect(CONTEXT_NOT_FOUND_ERROR_MESSAGE); - - let mut children = None; - - portal_ctx.0.update_value(|portals| { - let children_signal = if let Some(pos) = portals - .iter() - .position(|(type_id, _)| *type_id == id.type_id()) - { - portals[pos].1 - } else { - let children = create_rw_signal(cx, None); - - portals.push((id.type_id(), children)); - - children - }; - - children = Some(children_signal); - }); - - let children = children.unwrap(); - - move || { - children.with(|children| { - if let Some(children) = children { - children(cx).into_view(cx) - } else { - ().into_view(cx) - } - }) - } + let portal_ctx = use_context::().expect(CONTEXT_NOT_FOUND_ERROR_MESSAGE); + + let mut children = None; + + portal_ctx.0.update_value(|portals| { + let children_signal = if let Some(pos) = portals + .iter() + .position(|(type_id, _)| *type_id == id.type_id()) + { + portals[pos].1 + } else { + let children = create_rw_signal(None); + + portals.push((id.type_id(), children)); + + children + }; + + children = Some(children_signal); + }); + + let children = children.unwrap(); + + move || { + children.with(|children| { + if let Some(children) = children { + children.clone().into_view() + } else { + ().into_view() + } + }) + } } diff --git a/src/when.rs b/src/when.rs index 1372dbc..b5e10b7 100644 --- a/src/when.rs +++ b/src/when.rs @@ -1,9 +1,9 @@ // use leptos::*; api_planning! { - let (any_signal, _) = create_signal(cx, "apple"); + let (any_signal, _) = create_signal("apple"); - view! { cx, + view! { "show this" @@ -19,7 +19,7 @@ api_planning! { } // #[component] -// fn When(cx: Scope, signal: Signal) -> impl IntoView +// fn When(signal: Signal) -> impl IntoView // where // T: 'static, // { @@ -27,7 +27,7 @@ api_planning! { // } // #[component(transparent)] -// fn Is(cx: Scope, f: F) -> impl IntoView +// fn Is(f: F) -> impl IntoView // where // F: Fn(T) -> bool + 'static, // {