Skip to content

Commit ef13ae1

Browse files
committed
feat!: CsrStyle's State doesn't require Default
1 parent 468a9b6 commit ef13ae1

File tree

9 files changed

+379
-175
lines changed

9 files changed

+379
-175
lines changed

packages/frender-html/src/style.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,15 @@ impl<PM, S> UnpinnedNonReactiveRenderStateKind for Kind<PM, S> {
5252
}
5353

5454
impl<PM: HasStyleDomApi<BT>, V: CsrStyle, BT: BehaviorType> UnpinnedRenderWithBehavior<BT> for Property<PM, V> {
55-
type UnpinnedRenderStateKind = Kind<PM, V::UpdateWithState>;
55+
type UnpinnedRenderStateKind = Kind<PM, V::State>;
5656

5757
fn unpinned_render_init_with_behavior<R: ?Sized + crate::RenderHtml>(
5858
//
5959
Self { _prop_marker, value }: Self,
6060
renderer: &mut R,
6161
b: &mut <BT as crate::BehaviorType>::OfBehaviorType<R>,
6262
) -> <Self::UnpinnedRenderStateKind as crate::update_element::UnpinnedNonReactiveRenderStateKind>::UnpinnedNonReactiveState<R> {
63-
let mut state = Default::default();
64-
V::update_with_state(value, &mut state, &mut PM::style_dom_api(b, renderer));
65-
state
63+
V::csr_style_render_init(value, &mut PM::style_dom_api(b, renderer))
6664
}
6765

6866
fn unpinned_render_update_with_behavior<R: ?Sized + crate::RenderHtml>(
@@ -72,7 +70,7 @@ impl<PM: HasStyleDomApi<BT>, V: CsrStyle, BT: BehaviorType> UnpinnedRenderWithBe
7270
b: &mut <BT as crate::BehaviorType>::OfBehaviorType<R>,
7371
state: &mut <Self::UnpinnedRenderStateKind as crate::update_element::UnpinnedNonReactiveRenderStateKind>::UnpinnedNonReactiveState<R>,
7472
) {
75-
V::update_with_state(value, state, &mut PM::style_dom_api(b, renderer));
73+
V::csr_style_render_update(value, &mut PM::style_dom_api(b, renderer), state)
7674
}
7775
}
7876

packages/frender-style/src/csr.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,32 +100,64 @@ pub trait CssStyleDeclaration {
100100
}
101101
}
102102

103+
pub trait CsrStyleStateUnmount {
104+
/// Takes `&mut Self` instead of `Self` so that:
105+
/// - [`EitherStyle`](crate::styles::EitherStyle) can ensure old state is unmounted before new state is initialized,
106+
/// avoiding the case where they share same style declaration names.
107+
/// - `Preserved` can be implemented without additional traits.
108+
fn csr_style_state_unmount(state: &mut Self, style: &mut impl CssStyleDeclaration);
109+
}
110+
111+
impl CsrStyleStateUnmount for () {
112+
fn csr_style_state_unmount((): &mut Self, _: &mut impl CssStyleDeclaration) {}
113+
}
114+
103115
pub trait CsrStyle {
104-
type UpdateWithState: Default;
116+
type State: CsrStyleStateUnmount;
117+
118+
fn csr_style_render_init(this: Self, style: &mut impl CssStyleDeclaration) -> Self::State;
119+
120+
/// The `old_state` was [unmounted](CsrStyleStateUnmount::csr_style_state_unmount).
121+
fn csr_style_render_init_with_old_state(
122+
this: Self,
123+
style: &mut impl CssStyleDeclaration,
124+
old_state: &mut Self::State,
125+
) where
126+
Self: Sized,
127+
{
128+
*old_state = Self::csr_style_render_init(this, style)
129+
}
105130

106-
fn update_with_state(
131+
fn csr_style_render_update(
107132
this: Self,
108-
state: &mut Self::UpdateWithState,
109133
style: &mut impl CssStyleDeclaration,
134+
state: &mut Self::State,
110135
);
111-
fn remove_with_state(state: &mut Self::UpdateWithState, style: &mut impl CssStyleDeclaration);
112136
}
113137

114138
impl<S: IntoStyle> CsrStyle for S
115139
where
116140
S::IntoStyle: CsrStyle,
117141
{
118-
type UpdateWithState = <S::IntoStyle as CsrStyle>::UpdateWithState;
142+
type State = <S::IntoStyle as CsrStyle>::State;
143+
144+
fn csr_style_render_init(this: Self, style: &mut impl CssStyleDeclaration) -> Self::State {
145+
<S::IntoStyle>::csr_style_render_init(this.into_style(), style)
146+
}
119147

120-
fn update_with_state(
148+
fn csr_style_render_init_with_old_state(
121149
this: Self,
122-
state: &mut Self::UpdateWithState,
123150
style: &mut impl CssStyleDeclaration,
151+
old_state: &mut Self::State,
124152
) {
125-
<S::IntoStyle>::update_with_state(this.into_style(), state, style)
153+
<S::IntoStyle>::csr_style_render_init_with_old_state(this.into_style(), style, old_state)
126154
}
127155

128-
fn remove_with_state(state: &mut Self::UpdateWithState, style: &mut impl CssStyleDeclaration) {
129-
<S::IntoStyle>::remove_with_state(state, style)
156+
fn csr_style_render_update(
157+
this: Self,
158+
style: &mut impl CssStyleDeclaration,
159+
state: &mut Self::State,
160+
) {
161+
<S::IntoStyle>::csr_style_render_update(this.into_style(), style, state)
130162
}
131163
}

packages/frender-style/src/declaration/name.rs

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub mod ssr {
8383
pub mod csr {
8484
use frender_common::{strings::CsrStr, IntoStaticStrCache, ToAsRefStr};
8585

86-
use crate::csr::CssStyleDeclaration;
86+
use crate::csr::{CsrStyleStateUnmount, CssStyleDeclaration};
8787

8888
use super::DeclarationName;
8989

@@ -94,42 +94,84 @@ pub mod csr {
9494

9595
pub trait CsrDeclarationName {
9696
type Cacheable: IntoStaticStrCache<StaticStrCache = Self::StaticCache>;
97-
type StaticCache: 'static;
97+
98+
/// The [`CsrStyleStateUnmount`] allows to remove this style by name.
99+
type StaticCache: 'static + CsrStyleStateUnmount;
98100

99101
fn match_cache(this: &Self, cache: &Self::StaticCache) -> bool;
100102

101103
fn into_cacheable(this: Self) -> Self::Cacheable;
102104

103105
fn update_style(this: &Self::StaticCache, style: impl UpdateStyleWithDeclarationName);
106+
}
107+
108+
pub struct DeclarationNameStrCacheable<S>(pub S);
109+
110+
pub struct DeclarationNameStrStaticCache<S>(pub S);
111+
112+
impl<S: IntoStaticStrCache> IntoStaticStrCache for DeclarationNameStrCacheable<S> {
113+
type StaticStrCache = DeclarationNameStrStaticCache<S::StaticStrCache>;
114+
115+
fn into_static_str_cache(self) -> Self::StaticStrCache {
116+
DeclarationNameStrStaticCache(self.0.into_static_str_cache())
117+
}
118+
119+
fn update_into_static_str_cache(self, cache: &mut Self::StaticStrCache) {
120+
self.0.update_into_static_str_cache(&mut cache.0)
121+
}
122+
}
123+
124+
impl<S: PartialEq<T>, T> PartialEq<DeclarationNameStrCacheable<T>>
125+
for DeclarationNameStrStaticCache<S>
126+
{
127+
fn eq(&self, other: &DeclarationNameStrCacheable<T>) -> bool {
128+
self.0 == other.0
129+
}
130+
}
131+
132+
impl<S: ToAsRefStr> ToAsRefStr for DeclarationNameStrStaticCache<S> {
133+
type ToAsRefStr<'a> = S::ToAsRefStr<'a>
134+
where
135+
Self: 'a;
104136

105-
fn remove_style(this: &Self::StaticCache, style: &mut impl CssStyleDeclaration);
137+
fn to_as_ref_str(&self) -> Self::ToAsRefStr<'_> {
138+
self.0.to_as_ref_str()
139+
}
140+
}
141+
142+
/// This relies on StrToAsRefStr::to_as_ref_str and StrToStaticCache::IntoToStaticCache would AsRef the same string
143+
impl<S: ToAsRefStr> CsrStyleStateUnmount for DeclarationNameStrStaticCache<S> {
144+
fn csr_style_state_unmount(this: &mut Self, style: &mut impl CssStyleDeclaration) {
145+
style.remove_property_str(this.0.to_as_ref_str().as_ref())
146+
}
106147
}
107148

108149
impl<S: CsrStr> CsrDeclarationName for S {
109-
type Cacheable = S::IntoIntoStaticStrCache;
110-
type StaticCache = S::StaticStrCache;
150+
type Cacheable = DeclarationNameStrCacheable<S::IntoIntoStaticStrCache>;
151+
type StaticCache = DeclarationNameStrStaticCache<S::StaticStrCache>;
111152

112153
fn match_cache(this: &Self, cache: &Self::StaticCache) -> bool {
113-
cache == this
154+
cache.0 == *this
114155
}
115156

116157
fn into_cacheable(this: Self) -> Self::Cacheable {
117-
this.into_into_static_str_cache()
158+
DeclarationNameStrCacheable(this.into_into_static_str_cache())
118159
}
119160

120161
fn update_style(this: &Self::StaticCache, style: impl UpdateStyleWithDeclarationName) {
121162
style.update_style_with_declaration_name_str(this.to_as_ref_str().as_ref())
122163
}
123-
124-
/// This relies on StrToAsRefStr::to_as_ref_str and StrToStaticCache::IntoToStaticCache would AsRef the same string
125-
fn remove_style(this: &Self::StaticCache, style: &mut impl CssStyleDeclaration) {
126-
style.remove_property_str(this.to_as_ref_str().as_ref())
127-
}
128164
}
129165

130166
pub struct CacheableDeclarationName<S>(S);
131167
pub struct CacheableDeclarationNameIntoStaticStrCache<S>(S);
132168

169+
impl<S: ToAsRefStr> CsrStyleStateUnmount for CacheableDeclarationNameIntoStaticStrCache<S> {
170+
fn csr_style_state_unmount(this: &mut Self, style: &mut impl CssStyleDeclaration) {
171+
style.remove_property(DeclarationName(this.0.to_as_ref_str().as_ref()))
172+
}
173+
}
174+
133175
impl<S: ToAsRefStr> ToAsRefStr for CacheableDeclarationName<S> {
134176
type ToAsRefStr<'a> = S::ToAsRefStr<'a>
135177
where
@@ -192,9 +234,5 @@ pub mod csr {
192234
this.0.to_as_ref_str().as_ref(),
193235
))
194236
}
195-
196-
fn remove_style(this: &Self::StaticCache, style: &mut impl CssStyleDeclaration) {
197-
style.remove_property(DeclarationName(this.0.to_as_ref_str().as_ref()))
198-
}
199237
}
200238
}

packages/frender-style/src/styles/chain.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,49 @@ mod ssr {
1919
}
2020

2121
mod csr {
22-
use crate::csr::CsrStyle;
22+
use crate::csr::{CsrStyle, CsrStyleStateUnmount};
2323

2424
use super::Chain;
2525

26+
impl<A: CsrStyleStateUnmount, B: CsrStyleStateUnmount> CsrStyleStateUnmount for (A, B) {
27+
fn csr_style_state_unmount(
28+
(state_a, state_b): &mut Self,
29+
style: &mut impl crate::csr::CssStyleDeclaration,
30+
) {
31+
A::csr_style_state_unmount(state_a, style);
32+
B::csr_style_state_unmount(state_b, style);
33+
}
34+
}
35+
2636
impl<A: CsrStyle, B: CsrStyle> CsrStyle for Chain<A, B> {
27-
type UpdateWithState = (A::UpdateWithState, B::UpdateWithState);
37+
type State = (A::State, B::State);
2838

29-
fn update_with_state(
39+
fn csr_style_render_init(
3040
Self(a, b): Self,
31-
(state_a, state_b): &mut Self::UpdateWithState,
3241
style: &mut impl crate::csr::CssStyleDeclaration,
42+
) -> Self::State {
43+
(
44+
A::csr_style_render_init(a, style),
45+
B::csr_style_render_init(b, style),
46+
)
47+
}
48+
49+
fn csr_style_render_init_with_old_state(
50+
Self(a, b): Self,
51+
style: &mut impl crate::csr::CssStyleDeclaration,
52+
(old_state_a, old_state_b): &mut Self::State,
3353
) {
34-
A::update_with_state(a, state_a, style);
35-
B::update_with_state(b, state_b, style);
54+
A::csr_style_render_init_with_old_state(a, style, old_state_a);
55+
B::csr_style_render_init_with_old_state(b, style, old_state_b);
3656
}
3757

38-
fn remove_with_state(
39-
(state_a, state_b): &mut Self::UpdateWithState,
58+
fn csr_style_render_update(
59+
Self(a, b): Self,
4060
style: &mut impl crate::csr::CssStyleDeclaration,
61+
(state_a, state_b): &mut Self::State,
4162
) {
42-
A::remove_with_state(state_a, style);
43-
B::remove_with_state(state_b, style);
63+
A::csr_style_render_update(a, style, state_a);
64+
B::csr_style_render_update(b, style, state_b);
4465
}
4566
}
4667
}

packages/frender-style/src/styles/constness.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -683,23 +683,29 @@ pub mod ssr {
683683
}
684684

685685
pub mod csr {
686-
use crate::csr::CsrStyle;
686+
use std::marker::PhantomData;
687+
688+
use crate::csr::{CsrStyle, CsrStyleStateUnmount};
687689

688690
use super::{ConstDeclarationList, HasConstDeclarationList};
689691

692+
pub struct State<T: ?Sized + HasConstDeclarationList>(PhantomData<T>);
693+
694+
impl<T: ?Sized + HasConstDeclarationList> CsrStyleStateUnmount for State<T> {
695+
fn csr_style_state_unmount(_: &mut Self, style: &mut impl crate::csr::CssStyleDeclaration) {
696+
T::DECLARATION_LIST
697+
.into_iter()
698+
.for_each(|d| style.remove_property(d.name.as_ref_str()));
699+
}
700+
}
701+
690702
impl<T: ?Sized + HasConstDeclarationList> CsrStyle for ConstDeclarationList<T> {
691-
type UpdateWithState = bool; // whether updated
703+
type State = State<T>;
692704

693-
fn update_with_state(
705+
fn csr_style_render_init(
694706
_: Self,
695-
state: &mut Self::UpdateWithState,
696707
style: &mut impl crate::csr::CssStyleDeclaration,
697-
) {
698-
if *state {
699-
return;
700-
}
701-
*state = true;
702-
708+
) -> Self::State {
703709
T::DECLARATION_LIST.into_iter().for_each(|d| {
704710
let name = d.name;
705711
let value = d.value;
@@ -709,20 +715,16 @@ pub mod csr {
709715
value.as_ref_str(),
710716
d.important,
711717
);
712-
})
718+
});
719+
State(PhantomData)
713720
}
714721

715-
fn remove_with_state(
716-
state: &mut Self::UpdateWithState,
717-
style: &mut impl crate::csr::CssStyleDeclaration,
722+
fn csr_style_render_update(
723+
_: Self,
724+
_: &mut impl crate::csr::CssStyleDeclaration,
725+
_: &mut Self::State,
718726
) {
719-
if !*state {
720-
return;
721-
}
722-
*state = false;
723-
T::DECLARATION_LIST
724-
.into_iter()
725-
.for_each(|d| style.remove_property(d.name.as_ref_str()));
727+
return;
726728
}
727729
}
728730
}

0 commit comments

Comments
 (0)