From e4c977911c287e39072190e522e196dd9a477572 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Thu, 27 Feb 2025 16:41:53 +0330 Subject: [PATCH 1/7] Implement `IntoStyle` and `IntoStyleValue` for store fields --- tachys/src/reactive_graph/style.rs | 238 ++++++++++++++++++----------- 1 file changed, 145 insertions(+), 93 deletions(-) diff --git a/tachys/src/reactive_graph/style.rs b/tachys/src/reactive_graph/style.rs index 58fe7840cb..f1da82bae4 100644 --- a/tachys/src/reactive_graph/style.rs +++ b/tachys/src/reactive_graph/style.rs @@ -208,16 +208,18 @@ where #[cfg(not(feature = "nightly"))] mod stable { - macro_rules! style_signal { - ($sig:ident) => { - impl IntoStyle for $sig + macro_rules! style_store_field { + ($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) => + { + #[allow(deprecated)] + impl<$($gen),*> IntoStyle for $name<$($gen),*> where - $sig: Get, - C: IntoStyle + Clone + Send + Sync + 'static, - C::State: 'static, + $v: IntoStyle + Clone + Send + Sync + 'static, + <$v as IntoStyle>::State: 'static, + $($where_clause)* { type AsyncOutput = Self; - type State = RenderEffect; + type State = RenderEffect<<$v as IntoStyle>::State>; type Cloneable = Self; type CloneableOwned = Self; @@ -262,7 +264,7 @@ mod stable { *state = RenderEffect::new_with_value( move |prev| { if let Some(mut state) = prev { - C::reset(&mut state); + <$v>::reset(&mut state); state } else { unreachable!() @@ -273,15 +275,16 @@ mod stable { } } - impl IntoStyleValue for $sig + #[allow(deprecated)] + impl<$($gen),*> IntoStyleValue for $name<$($gen),*> where - $sig: Get, - S: IntoStyleValue + Send + Sync + Clone + 'static, + $v: IntoStyleValue + Send + Sync + Clone + 'static, + $($where_clause)* { type AsyncOutput = Self; - type State = (Arc, RenderEffect); - type Cloneable = $sig; - type CloneableOwned = $sig; + type State = (Arc, RenderEffect<<$v as IntoStyleValue>::State>); + type Cloneable = $name<$($gen),*>; + type CloneableOwned = $name<$($gen),*>; fn to_html(self, name: &str, style: &mut String) { IntoStyleValue::to_html(move || self.get(), name, style) @@ -334,76 +337,6 @@ mod stable { }; } - macro_rules! style_signal_arena { - ($sig:ident) => { - #[allow(deprecated)] - impl IntoStyle for $sig - where - $sig: Get, - S: Storage + Storage>, - S: Send + Sync + 'static, - C: IntoStyle + Send + Sync + Clone + 'static, - C::State: 'static, - { - type AsyncOutput = Self; - type State = RenderEffect; - type Cloneable = Self; - type CloneableOwned = Self; - - fn to_html(self, style: &mut String) { - let value = self.get(); - value.to_html(style); - } - - fn hydrate( - self, - el: &crate::renderer::types::Element, - ) -> Self::State { - (move || self.get()).hydrate::(el) - } - - fn build( - self, - el: &crate::renderer::types::Element, - ) -> Self::State { - (move || self.get()).build(el) - } - - fn rebuild(self, state: &mut Self::State) { - (move || self.get()).rebuild(state) - } - - fn into_cloneable(self) -> Self::Cloneable { - self - } - - fn into_cloneable_owned(self) -> Self::CloneableOwned { - self - } - - fn dry_resolve(&mut self) {} - - async fn resolve(self) -> Self::AsyncOutput { - self - } - - fn reset(state: &mut Self::State) { - *state = RenderEffect::new_with_value( - move |prev| { - if let Some(mut state) = prev { - C::reset(&mut state); - state - } else { - unreachable!() - } - }, - state.take_value(), - ); - } - } - }; - } - use super::RenderEffect; use crate::html::style::{IntoStyle, IntoStyleValue}; #[allow(deprecated)] @@ -417,15 +350,134 @@ mod stable { }; use std::sync::Arc; - style_signal_arena!(RwSignal); - style_signal_arena!(ReadSignal); - style_signal_arena!(Memo); - style_signal_arena!(Signal); - style_signal_arena!(MaybeSignal); - style_signal!(ArcRwSignal); - style_signal!(ArcReadSignal); - style_signal!(ArcMemo); - style_signal!(ArcSignal); + style_store_field!( + RwSignal, + , + V, + RwSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + style_store_field!( + ReadSignal, + , + V, + ReadSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + style_store_field!( + Memo, + , + V, + Memo: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + style_store_field!( + Signal, + , + V, + Signal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + style_store_field!( + MaybeSignal, + , + V, + MaybeSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + style_store_field!(ArcRwSignal, , V, ArcRwSignal: Get); + style_store_field!(ArcReadSignal, , V, ArcReadSignal: Get); + style_store_field!(ArcMemo, , V, ArcMemo: Get); + style_store_field!(ArcSignal, , V, ArcSignal: Get); + + #[cfg(feature = "reactive_stores")] + use { + reactive_stores::{ + ArcField, ArcStore, AtIndex, AtKeyed, DerefedField, Field, + KeyedSubfield, Store, StoreField, Subfield, + }, + std::ops::{Deref, DerefMut, Index, IndexMut}, + }; + + #[cfg(feature = "reactive_stores")] + style_store_field!( + Subfield, + , + V, + Subfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + ); + + #[cfg(feature = "reactive_stores")] + style_store_field!( + AtKeyed, + , + V, + AtKeyed: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); + + #[cfg(feature = "reactive_stores")] + style_store_field!( + KeyedSubfield, + , + V, + KeyedSubfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); + + #[cfg(feature = "reactive_stores")] + style_store_field!( + DerefedField, + , + ::Target, + S: Clone + StoreField + Send + Sync + 'static, + ::Value: Deref + DerefMut + ); + + #[cfg(feature = "reactive_stores")] + style_store_field!( + AtIndex, + , + >::Output, + AtIndex: Get, + Prev: Send + Sync + IndexMut + 'static, + Inner: Send + Sync + Clone + 'static, + ); + #[cfg(feature = "reactive_stores")] + style_store_field!( + Store, + , + V, + Store: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + style_store_field!( + Field, + , + V, + Field: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + style_store_field!(ArcStore, , V, ArcStore: Get); + #[cfg(feature = "reactive_stores")] + style_store_field!(ArcField, , V, ArcField: Get); } /* From c524b0aefc81e5db789e2f0c3535b85cd2598ad0 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Thu, 27 Feb 2025 16:55:37 +0330 Subject: [PATCH 2/7] rename `style_store_field` macro to `style_reactive` --- tachys/src/reactive_graph/style.rs | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tachys/src/reactive_graph/style.rs b/tachys/src/reactive_graph/style.rs index f1da82bae4..b77ca0a7f4 100644 --- a/tachys/src/reactive_graph/style.rs +++ b/tachys/src/reactive_graph/style.rs @@ -208,7 +208,7 @@ where #[cfg(not(feature = "nightly"))] mod stable { - macro_rules! style_store_field { + macro_rules! style_reactive { ($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) => { #[allow(deprecated)] @@ -350,7 +350,7 @@ mod stable { }; use std::sync::Arc; - style_store_field!( + style_reactive!( RwSignal, , V, @@ -358,7 +358,7 @@ mod stable { S: Storage + Storage>, S: Send + Sync + 'static, ); - style_store_field!( + style_reactive!( ReadSignal, , V, @@ -366,7 +366,7 @@ mod stable { S: Storage + Storage>, S: Send + Sync + 'static, ); - style_store_field!( + style_reactive!( Memo, , V, @@ -374,7 +374,7 @@ mod stable { S: Storage + Storage>, S: Send + Sync + 'static, ); - style_store_field!( + style_reactive!( Signal, , V, @@ -382,7 +382,7 @@ mod stable { S: Storage + Storage>, S: Send + Sync + 'static, ); - style_store_field!( + style_reactive!( MaybeSignal, , V, @@ -390,10 +390,10 @@ mod stable { S: Storage + Storage>, S: Send + Sync + 'static, ); - style_store_field!(ArcRwSignal, , V, ArcRwSignal: Get); - style_store_field!(ArcReadSignal, , V, ArcReadSignal: Get); - style_store_field!(ArcMemo, , V, ArcMemo: Get); - style_store_field!(ArcSignal, , V, ArcSignal: Get); + style_reactive!(ArcRwSignal, , V, ArcRwSignal: Get); + style_reactive!(ArcReadSignal, , V, ArcReadSignal: Get); + style_reactive!(ArcMemo, , V, ArcMemo: Get); + style_reactive!(ArcSignal, , V, ArcSignal: Get); #[cfg(feature = "reactive_stores")] use { @@ -405,7 +405,7 @@ mod stable { }; #[cfg(feature = "reactive_stores")] - style_store_field!( + style_reactive!( Subfield, , V, @@ -415,7 +415,7 @@ mod stable { ); #[cfg(feature = "reactive_stores")] - style_store_field!( + style_reactive!( AtKeyed, , V, @@ -427,7 +427,7 @@ mod stable { ); #[cfg(feature = "reactive_stores")] - style_store_field!( + style_reactive!( KeyedSubfield, , V, @@ -439,7 +439,7 @@ mod stable { ); #[cfg(feature = "reactive_stores")] - style_store_field!( + style_reactive!( DerefedField, , ::Target, @@ -448,7 +448,7 @@ mod stable { ); #[cfg(feature = "reactive_stores")] - style_store_field!( + style_reactive!( AtIndex, , >::Output, @@ -457,7 +457,7 @@ mod stable { Inner: Send + Sync + Clone + 'static, ); #[cfg(feature = "reactive_stores")] - style_store_field!( + style_reactive!( Store, , V, @@ -466,7 +466,7 @@ mod stable { S: Send + Sync + 'static, ); #[cfg(feature = "reactive_stores")] - style_store_field!( + style_reactive!( Field, , V, @@ -475,9 +475,9 @@ mod stable { S: Send + Sync + 'static, ); #[cfg(feature = "reactive_stores")] - style_store_field!(ArcStore, , V, ArcStore: Get); + style_reactive!(ArcStore, , V, ArcStore: Get); #[cfg(feature = "reactive_stores")] - style_store_field!(ArcField, , V, ArcField: Get); + style_reactive!(ArcField, , V, ArcField: Get); } /* From 2d1b66a5c6da3fc21f8a951c1d041b8bf28d7c6a Mon Sep 17 00:00:00 2001 From: Mahdi Date: Thu, 27 Feb 2025 17:00:33 +0330 Subject: [PATCH 3/7] Implement `IntoProperty` for store fields --- tachys/src/reactive_graph/property.rs | 187 ++++++++++++++++++-------- 1 file changed, 131 insertions(+), 56 deletions(-) diff --git a/tachys/src/reactive_graph/property.rs b/tachys/src/reactive_graph/property.rs index a2406e0896..1913c33329 100644 --- a/tachys/src/reactive_graph/property.rs +++ b/tachys/src/reactive_graph/property.rs @@ -93,15 +93,17 @@ mod stable { wrappers::read::{ArcSignal, Signal}, }; - macro_rules! property_signal { - ($sig:ident) => { - impl IntoProperty for $sig + macro_rules! property_reactive { + ($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) => + { + #[allow(deprecated)] + impl<$($gen),*> IntoProperty for $name<$($gen),*> where - $sig: Get, - V: IntoProperty + Send + Sync + Clone + 'static, - V::State: 'static, + $v: IntoProperty + Clone + Send + Sync + 'static, + <$v as IntoProperty>::State: 'static, + $($where_clause)* { - type State = RenderEffect; + type State = RenderEffect<<$v as IntoProperty>::State>; type Cloneable = Self; type CloneableOwned = Self; @@ -136,59 +138,132 @@ mod stable { }; } - macro_rules! property_signal_arena { - ($sig:ident) => { - #[allow(deprecated)] - impl IntoProperty for $sig - where - $sig: Get, - S: Send + Sync + 'static, - S: Storage + Storage>, - V: IntoProperty + Send + Sync + Clone + 'static, - V::State: 'static, - { - type State = RenderEffect; - type Cloneable = Self; - type CloneableOwned = Self; + property_reactive!( + RwSignal, + , + V, + RwSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + property_reactive!( + ReadSignal, + , + V, + ReadSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + property_reactive!( + Memo, + , + V, + Memo: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + property_reactive!( + Signal, + , + V, + Signal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + property_reactive!( + MaybeSignal, + , + V, + MaybeSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + property_reactive!(ArcRwSignal, , V, ArcRwSignal: Get); + property_reactive!(ArcReadSignal, , V, ArcReadSignal: Get); + property_reactive!(ArcMemo, , V, ArcMemo: Get); + property_reactive!(ArcSignal, , V, ArcSignal: Get); - fn hydrate( - self, - el: &crate::renderer::types::Element, - key: &str, - ) -> Self::State { - (move || self.get()).hydrate::(el, key) - } + #[cfg(feature = "reactive_stores")] + use { + reactive_stores::{ + ArcField, ArcStore, AtIndex, AtKeyed, DerefedField, Field, + KeyedSubfield, Store, StoreField, Subfield, + }, + std::ops::{Deref, DerefMut, Index, IndexMut}, + }; - fn build( - self, - el: &crate::renderer::types::Element, - key: &str, - ) -> Self::State { - (move || self.get()).build(el, key) - } + #[cfg(feature = "reactive_stores")] + property_reactive!( + Subfield, + , + V, + Subfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + ); - fn rebuild(self, state: &mut Self::State, key: &str) { - (move || self.get()).rebuild(state, key) - } + #[cfg(feature = "reactive_stores")] + property_reactive!( + AtKeyed, + , + V, + AtKeyed: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); - fn into_cloneable(self) -> Self::Cloneable { - self - } + #[cfg(feature = "reactive_stores")] + property_reactive!( + KeyedSubfield, + , + V, + KeyedSubfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); - fn into_cloneable_owned(self) -> Self::CloneableOwned { - self - } - } - }; - } + #[cfg(feature = "reactive_stores")] + property_reactive!( + DerefedField, + , + ::Target, + S: Clone + StoreField + Send + Sync + 'static, + ::Value: Deref + DerefMut + ); - property_signal_arena!(RwSignal); - property_signal_arena!(ReadSignal); - property_signal_arena!(Memo); - property_signal_arena!(Signal); - property_signal_arena!(MaybeSignal); - property_signal!(ArcRwSignal); - property_signal!(ArcReadSignal); - property_signal!(ArcMemo); - property_signal!(ArcSignal); + #[cfg(feature = "reactive_stores")] + property_reactive!( + AtIndex, + , + >::Output, + AtIndex: Get, + Prev: Send + Sync + IndexMut + 'static, + Inner: Send + Sync + Clone + 'static, + ); + #[cfg(feature = "reactive_stores")] + property_reactive!( + Store, + , + V, + Store: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + property_reactive!( + Field, + , + V, + Field: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + property_reactive!(ArcStore, , V, ArcStore: Get); + #[cfg(feature = "reactive_stores")] + property_reactive!(ArcField, , V, ArcField: Get); } From 1a472ebad19f0b549f1fa7efba1a030cea87cc2c Mon Sep 17 00:00:00 2001 From: Mahdi Date: Thu, 27 Feb 2025 17:09:34 +0330 Subject: [PATCH 4/7] Implement `InnerHtmlValue` for store fields --- tachys/src/reactive_graph/inner_html.rs | 213 +++++++++++++++--------- 1 file changed, 136 insertions(+), 77 deletions(-) diff --git a/tachys/src/reactive_graph/inner_html.rs b/tachys/src/reactive_graph/inner_html.rs index ab2129b1d1..0a2b419d6c 100644 --- a/tachys/src/reactive_graph/inner_html.rs +++ b/tachys/src/reactive_graph/inner_html.rs @@ -100,78 +100,18 @@ mod stable { wrappers::read::{ArcSignal, Signal}, }; - macro_rules! inner_html_signal { - ($sig:ident) => { - impl InnerHtmlValue for $sig - where - $sig: Get, - V: InnerHtmlValue + Send + Sync + Clone + 'static, - V::State: 'static, - { - type AsyncOutput = Self; - type State = RenderEffect; - type Cloneable = Self; - type CloneableOwned = Self; - - fn html_len(&self) -> usize { - 0 - } - - fn to_html(self, buf: &mut String) { - let value = self.get(); - value.to_html(buf); - } - - fn to_template(_buf: &mut String) {} - - fn hydrate( - self, - el: &crate::renderer::types::Element, - ) -> Self::State { - (move || self.get()).hydrate::(el) - } - - fn build( - self, - el: &crate::renderer::types::Element, - ) -> Self::State { - (move || self.get()).build(el) - } - - fn rebuild(self, state: &mut Self::State) { - (move || self.get()).rebuild(state) - } - - fn into_cloneable(self) -> Self::Cloneable { - self - } - - fn into_cloneable_owned(self) -> Self::CloneableOwned { - self - } - - fn dry_resolve(&mut self) {} - - async fn resolve(self) -> Self::AsyncOutput { - self - } - } - }; - } - - macro_rules! inner_html_signal_arena { - ($sig:ident) => { + macro_rules! inner_html_reactive { + ($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) => + { #[allow(deprecated)] - impl InnerHtmlValue for $sig + impl<$($gen),*> InnerHtmlValue for $name<$($gen),*> where - $sig: Get, - S: Send + Sync + 'static, - S: Storage, - V: InnerHtmlValue + Send + Sync + Clone + 'static, - V::State: 'static, + $v: InnerHtmlValue + Clone + Send + Sync + 'static, + <$v as InnerHtmlValue>::State: 'static, + $($where_clause)* { type AsyncOutput = Self; - type State = RenderEffect; + type State = RenderEffect<<$v as InnerHtmlValue>::State>; type Cloneable = Self; type CloneableOwned = Self; @@ -221,13 +161,132 @@ mod stable { }; } - inner_html_signal_arena!(RwSignal); - inner_html_signal_arena!(ReadSignal); - inner_html_signal_arena!(Memo); - inner_html_signal_arena!(Signal); - inner_html_signal_arena!(MaybeSignal); - inner_html_signal!(ArcRwSignal); - inner_html_signal!(ArcReadSignal); - inner_html_signal!(ArcMemo); - inner_html_signal!(ArcSignal); + inner_html_reactive!( + RwSignal, + , + V, + RwSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + inner_html_reactive!( + ReadSignal, + , + V, + ReadSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + inner_html_reactive!( + Memo, + , + V, + Memo: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + inner_html_reactive!( + Signal, + , + V, + Signal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + inner_html_reactive!( + MaybeSignal, + , + V, + MaybeSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + inner_html_reactive!(ArcRwSignal, , V, ArcRwSignal: Get); + inner_html_reactive!(ArcReadSignal, , V, ArcReadSignal: Get); + inner_html_reactive!(ArcMemo, , V, ArcMemo: Get); + inner_html_reactive!(ArcSignal, , V, ArcSignal: Get); + + #[cfg(feature = "reactive_stores")] + use { + reactive_stores::{ + ArcField, ArcStore, AtIndex, AtKeyed, DerefedField, Field, + KeyedSubfield, Store, StoreField, Subfield, + }, + std::ops::{Deref, DerefMut, Index, IndexMut}, + }; + + #[cfg(feature = "reactive_stores")] + inner_html_reactive!( + Subfield, + , + V, + Subfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + ); + + #[cfg(feature = "reactive_stores")] + inner_html_reactive!( + AtKeyed, + , + V, + AtKeyed: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); + + #[cfg(feature = "reactive_stores")] + inner_html_reactive!( + KeyedSubfield, + , + V, + KeyedSubfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); + + #[cfg(feature = "reactive_stores")] + inner_html_reactive!( + DerefedField, + , + ::Target, + S: Clone + StoreField + Send + Sync + 'static, + ::Value: Deref + DerefMut + ); + + #[cfg(feature = "reactive_stores")] + inner_html_reactive!( + AtIndex, + , + >::Output, + AtIndex: Get, + Prev: Send + Sync + IndexMut + 'static, + Inner: Send + Sync + Clone + 'static, + ); + #[cfg(feature = "reactive_stores")] + inner_html_reactive!( + Store, + , + V, + Store: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + inner_html_reactive!( + Field, + , + V, + Field: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + inner_html_reactive!(ArcStore, , V, ArcStore: Get); + #[cfg(feature = "reactive_stores")] + inner_html_reactive!(ArcField, , V, ArcField: Get); } From fb608158cb6cc7abc2421bf4a0d0ae3c86865f1c Mon Sep 17 00:00:00 2001 From: Mahdi Date: Thu, 27 Feb 2025 17:16:51 +0330 Subject: [PATCH 5/7] Implement `IntoSplitSignal` for `AtKeyed`, `AtIndex` and `DerefedField` --- tachys/src/reactive_graph/bind.rs | 64 +++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/tachys/src/reactive_graph/bind.rs b/tachys/src/reactive_graph/bind.rs index 481e799196..b52ff8836a 100644 --- a/tachys/src/reactive_graph/bind.rs +++ b/tachys/src/reactive_graph/bind.rs @@ -14,17 +14,22 @@ use crate::{ renderer::{types::Element, RemoveEventHandler}, view::{Position, ToTemplate}, }; -#[cfg(feature = "reactive_stores")] -use reactive_graph::owner::Storage; use reactive_graph::{ signal::{ReadSignal, RwSignal, WriteSignal}, traits::{Get, Set}, wrappers::read::Signal, }; -#[cfg(feature = "reactive_stores")] -use reactive_stores::{ArcField, Field, KeyedSubfield, Subfield}; use send_wrapper::SendWrapper; use wasm_bindgen::JsValue; +#[cfg(feature = "reactive_stores")] +use { + reactive_graph::owner::Storage, + reactive_stores::{ + ArcField, AtIndex, AtKeyed, DerefedField, Field, KeyedSubfield, + StoreField, Subfield, + }, + std::ops::{Deref, DerefMut, IndexMut}, +}; /// `group` attribute used for radio inputs with `bind`. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -395,6 +400,57 @@ where } } +#[cfg(feature = "reactive_stores")] +impl IntoSplitSignal for AtKeyed +where + Self: Get + Set + Clone, + for<'a> &'a T: IntoIterator, +{ + type Value = T; + type Read = Self; + type Write = Self; + + fn into_split_signal(self) -> (Self::Read, Self::Write) { + (self.clone(), self.clone()) + } +} + +#[cfg(feature = "reactive_stores")] +impl IntoSplitSignal for AtIndex +where + Prev: Send + Sync + IndexMut + 'static, + Inner: Send + Sync + Clone + 'static, + Self: Get + Set + Clone, + Prev::Output: Sized, +{ + type Value = Prev::Output; + type Read = Self; + type Write = Self; + + fn into_split_signal(self) -> (Self::Read, Self::Write) { + (self.clone(), self.clone()) + } +} + +#[cfg(feature = "reactive_stores")] +impl IntoSplitSignal for DerefedField +where + Self: Get::Target> + + Set::Target> + + Clone, + S: Clone + StoreField + Send + Sync + 'static, + ::Value: Deref + DerefMut, + ::Target: Sized, +{ + type Value = ::Target; + type Read = Self; + type Write = Self; + + fn into_split_signal(self) -> (Self::Read, Self::Write) { + (self.clone(), self.clone()) + } +} + /// Returns self from an event target. pub trait FromEventTarget { /// Returns self from an event target. From db10d961dfd4cd1e44262f85cd952dede092ba9b Mon Sep 17 00:00:00 2001 From: Mahdi Date: Thu, 27 Feb 2025 17:44:07 +0330 Subject: [PATCH 6/7] Implement `Render`, `RenderHtml`, `AttributeValue` for store fields --- tachys/src/reactive_graph/mod.rs | 381 +++++++++++++------------------ 1 file changed, 163 insertions(+), 218 deletions(-) diff --git a/tachys/src/reactive_graph/mod.rs b/tachys/src/reactive_graph/mod.rs index b8b179345a..28fee097b5 100644 --- a/tachys/src/reactive_graph/mod.rs +++ b/tachys/src/reactive_graph/mod.rs @@ -579,197 +579,17 @@ mod stable { wrappers::read::{ArcSignal, Signal}, }; - macro_rules! signal_impl { - ($sig:ident $dry_resolve:literal) => { - impl Render for $sig - where - $sig: Get, - V: Render + Clone + Send + Sync + 'static, - V::State: 'static, - { - type State = RenderEffectState; - - #[track_caller] - fn build(self) -> Self::State { - (move || self.get()).build() - } - - #[track_caller] - fn rebuild(self, state: &mut Self::State) { - let new = self.build(); - let mut old = std::mem::replace(state, new); - old.insert_before_this(state); - old.unmount(); - } - } - - impl AddAnyAttr for $sig - where - $sig: Get, - V: RenderHtml + Clone + Send + Sync + 'static, - V::State: 'static, - { - type Output = Self; - - fn add_any_attr( - self, - _attr: NewAttr, - ) -> Self::Output - where - Self::Output: RenderHtml, - { - todo!() - } - } - - impl RenderHtml for $sig - where - $sig: Get, - V: RenderHtml + Clone + Send + Sync + 'static, - V::State: 'static, - { - type AsyncOutput = Self; - type Owned = Self; - - const MIN_LENGTH: usize = 0; - - fn dry_resolve(&mut self) { - if $dry_resolve { - _ = self.get(); - } - } - - async fn resolve(self) -> Self::AsyncOutput { - self - } - - fn html_len(&self) -> usize { - V::MIN_LENGTH - } - - fn to_html_with_buf( - self, - buf: &mut String, - position: &mut Position, - escape: bool, - mark_branches: bool, - extra_attrs: Vec, - ) { - let value = self.get(); - value.to_html_with_buf( - buf, - position, - escape, - mark_branches, - extra_attrs, - ) - } - - fn to_html_async_with_buf( - self, - buf: &mut StreamBuilder, - position: &mut Position, - escape: bool, - mark_branches: bool, - extra_attrs: Vec, - ) where - Self: Sized, - { - let value = self.get(); - value.to_html_async_with_buf::( - buf, - position, - escape, - mark_branches, - extra_attrs, - ); - } - - fn hydrate( - self, - cursor: &Cursor, - position: &PositionState, - ) -> Self::State { - (move || self.get()) - .hydrate::(cursor, position) - } - - fn into_owned(self) -> Self::Owned { - self - } - } - - impl AttributeValue for $sig - where - $sig: Get, - V: AttributeValue + Clone + Send + Sync + 'static, - V::State: 'static, - { - type AsyncOutput = Self; - type State = RenderEffect; - type Cloneable = Self; - type CloneableOwned = Self; - - fn html_len(&self) -> usize { - 0 - } - - fn to_html(self, key: &str, buf: &mut String) { - let value = self.get(); - value.to_html(key, buf); - } - - fn to_template(_key: &str, _buf: &mut String) {} - - fn hydrate( - self, - key: &str, - el: &crate::renderer::types::Element, - ) -> Self::State { - (move || self.get()).hydrate::(key, el) - } - - fn build( - self, - el: &crate::renderer::types::Element, - key: &str, - ) -> Self::State { - (move || self.get()).build(el, key) - } - - fn rebuild(self, key: &str, state: &mut Self::State) { - (move || self.get()).rebuild(key, state) - } - - fn into_cloneable(self) -> Self::Cloneable { - self - } - - fn into_cloneable_owned(self) -> Self::CloneableOwned { - self - } - - fn dry_resolve(&mut self) {} - - async fn resolve(self) -> Self::AsyncOutput { - self - } - } - }; - } - - macro_rules! signal_impl_arena { - ($sig:ident $dry_resolve:literal) => { + macro_rules! reactive_impl { + ($name:ident, <$($gen:ident),*>, $v:ty, $dry_resolve:literal, $( $where_clause:tt )*) => + { #[allow(deprecated)] - impl Render for $sig + impl<$($gen),*> Render for $name<$($gen),*> where - $sig: Get, - S: Send + Sync + 'static, - S: Storage + Storage>, - V: Render + Send + Sync + Clone + 'static, - V::State: 'static, + $v: Render + Clone + Send + Sync + 'static, + <$v as Render>::State: 'static, + $($where_clause)* { - type State = RenderEffectState; + type State = RenderEffectState<<$v as Render>::State>; #[track_caller] fn build(self) -> Self::State { @@ -786,15 +606,13 @@ mod stable { } #[allow(deprecated)] - impl AddAnyAttr for $sig + impl<$($gen),*> AddAnyAttr for $name<$($gen),*> where - $sig: Get, - S: Send + Sync + 'static, - S: Storage + Storage>, - V: RenderHtml + Clone + Send + Sync + 'static, - V::State: 'static, + $v: RenderHtml + Clone + Send + Sync + 'static, + <$v as Render>::State: 'static, + $($where_clause)* { - type Output = $sig; + type Output = Self; fn add_any_attr( self, @@ -808,13 +626,11 @@ mod stable { } #[allow(deprecated)] - impl RenderHtml for $sig + impl<$($gen),*> RenderHtml for $name<$($gen),*> where - $sig: Get, - S: Send + Sync + 'static, - S: Storage + Storage>, - V: RenderHtml + Clone + Send + Sync + 'static, - V::State: 'static, + $v: RenderHtml + Clone + Send + Sync + 'static, + <$v as Render>::State: 'static, + $($where_clause)* { type AsyncOutput = Self; type Owned = Self; @@ -832,7 +648,7 @@ mod stable { } fn html_len(&self) -> usize { - V::MIN_LENGTH + <$v>::MIN_LENGTH } fn to_html_with_buf( @@ -888,16 +704,14 @@ mod stable { } #[allow(deprecated)] - impl AttributeValue for $sig + impl<$($gen),*> AttributeValue for $name<$($gen),*> where - $sig: Get, - S: Storage + Storage>, - S: Send + Sync + 'static, - V: AttributeValue + Send + Sync + Clone + 'static, - V::State: 'static, + $v: AttributeValue + Send + Sync + Clone + 'static, + <$v as AttributeValue>::State: 'static, + $($where_clause)* { type AsyncOutput = Self; - type State = RenderEffect; + type State = RenderEffect<<$v as AttributeValue>::State>; type Cloneable = Self; type CloneableOwned = Self; @@ -949,15 +763,146 @@ mod stable { }; } - signal_impl_arena!(RwSignal false); - signal_impl_arena!(ReadSignal false); - signal_impl_arena!(Memo true); - signal_impl_arena!(Signal true); - signal_impl_arena!(MaybeSignal true); - signal_impl!(ArcRwSignal false); - signal_impl!(ArcReadSignal false); - signal_impl!(ArcMemo false); - signal_impl!(ArcSignal true); + reactive_impl!( + RwSignal, + , + V, + false, + RwSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + reactive_impl!( + ReadSignal, + , + V, + false, + ReadSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + reactive_impl!( + Memo, + , + V, + true, + Memo: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + reactive_impl!( + Signal, + , + V, + true, + Signal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + reactive_impl!( + MaybeSignal, + , + V, + true, + MaybeSignal: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + reactive_impl!(ArcRwSignal, , V, false, ArcRwSignal: Get); + reactive_impl!(ArcReadSignal, , V, false, ArcReadSignal: Get); + reactive_impl!(ArcMemo, , V, false, ArcMemo: Get); + reactive_impl!(ArcSignal, , V, true, ArcSignal: Get); + + #[cfg(feature = "reactive_stores")] + use { + reactive_stores::{ + ArcField, ArcStore, AtIndex, AtKeyed, DerefedField, Field, + KeyedSubfield, Store, StoreField, Subfield, + }, + std::ops::{Deref, DerefMut, Index, IndexMut}, + }; + + #[cfg(feature = "reactive_stores")] + reactive_impl!( + Subfield, + , + V, + false, + Subfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + ); + + #[cfg(feature = "reactive_stores")] + reactive_impl!( + AtKeyed, + , + V, + false, + AtKeyed: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); + + #[cfg(feature = "reactive_stores")] + reactive_impl!( + KeyedSubfield, + , + V, + false, + KeyedSubfield: Get, + Prev: Send + Sync + 'static, + Inner: Send + Sync + Clone + 'static, + K: Send + Sync + std::fmt::Debug + Clone + 'static, + for<'a> &'a V: IntoIterator, + ); + + #[cfg(feature = "reactive_stores")] + reactive_impl!( + DerefedField, + , + ::Target, + false, + S: Clone + StoreField + Send + Sync + 'static, + ::Value: Deref + DerefMut + ); + + #[cfg(feature = "reactive_stores")] + reactive_impl!( + AtIndex, + , + >::Output, + false, + AtIndex: Get, + Prev: Send + Sync + IndexMut + 'static, + Inner: Send + Sync + Clone + 'static, + ); + #[cfg(feature = "reactive_stores")] + reactive_impl!( + Store, + , + V, + false, + Store: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + reactive_impl!( + Field, + , + V, + false, + Field: Get, + S: Storage + Storage>, + S: Send + Sync + 'static, + ); + #[cfg(feature = "reactive_stores")] + reactive_impl!(ArcStore, , V, false, ArcStore: Get); + #[cfg(feature = "reactive_stores")] + reactive_impl!(ArcField, , V, false, ArcField: Get); } /* From a9a988e0e10392f6b721f5d694dccc93805ea695 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 14:46:56 +0000 Subject: [PATCH 7/7] [autofix.ci] apply automated fixes --- tachys/src/reactive_graph/style.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tachys/src/reactive_graph/style.rs b/tachys/src/reactive_graph/style.rs index b77ca0a7f4..16f0bc5eec 100644 --- a/tachys/src/reactive_graph/style.rs +++ b/tachys/src/reactive_graph/style.rs @@ -394,7 +394,7 @@ mod stable { style_reactive!(ArcReadSignal, , V, ArcReadSignal: Get); style_reactive!(ArcMemo, , V, ArcMemo: Get); style_reactive!(ArcSignal, , V, ArcSignal: Get); - + #[cfg(feature = "reactive_stores")] use { reactive_stores::{