Skip to main content

leptos/
text_prop.rs

1use oco_ref::Oco;
2use std::sync::Arc;
3use tachys::prelude::IntoAttributeValue;
4
5/// Describes a value that is either a static or a reactive string, i.e.,
6/// a [`String`], a [`&str`], a `Signal` or a reactive `Fn() -> String`.
7#[derive(Clone)]
8pub struct TextProp(Arc<dyn Fn() -> Oco<'static, str> + Send + Sync>);
9
10impl TextProp {
11    /// Accesses the current value of the property.
12    #[inline(always)]
13    pub fn get(&self) -> Oco<'static, str> {
14        (self.0)()
15    }
16}
17
18impl core::fmt::Debug for TextProp {
19    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20        f.debug_tuple("TextProp").finish()
21    }
22}
23
24impl From<String> for TextProp {
25    fn from(s: String) -> Self {
26        let s: Oco<'_, str> = Oco::Counted(Arc::from(s));
27        TextProp(Arc::new(move || s.clone()))
28    }
29}
30
31impl From<&'static str> for TextProp {
32    fn from(s: &'static str) -> Self {
33        let s: Oco<'_, str> = s.into();
34        TextProp(Arc::new(move || s.clone()))
35    }
36}
37
38impl From<Arc<str>> for TextProp {
39    fn from(s: Arc<str>) -> Self {
40        let s: Oco<'_, str> = s.into();
41        TextProp(Arc::new(move || s.clone()))
42    }
43}
44
45impl From<Oco<'static, str>> for TextProp {
46    fn from(s: Oco<'static, str>) -> Self {
47        TextProp(Arc::new(move || s.clone()))
48    }
49}
50
51// TODO
52/*impl<T> From<T> for MaybeProp<TextProp>
53where
54    T: Into<Oco<'static, str>>,
55{
56    fn from(s: T) -> Self {
57        Self(Some(MaybeSignal::from(Some(s.into().into()))))
58    }
59}*/
60
61impl<F, S> From<F> for TextProp
62where
63    F: Fn() -> S + 'static + Send + Sync,
64    S: Into<Oco<'static, str>>,
65{
66    #[inline(always)]
67    fn from(s: F) -> Self {
68        TextProp(Arc::new(move || s().into()))
69    }
70}
71
72impl Default for TextProp {
73    fn default() -> Self {
74        Self(Arc::new(|| Oco::Borrowed("")))
75    }
76}
77
78impl IntoAttributeValue for TextProp {
79    type Output = Arc<dyn Fn() -> Oco<'static, str> + Send + Sync>;
80
81    fn into_attribute_value(self) -> Self::Output {
82        self.0
83    }
84}
85
86#[allow(unused)]
87macro_rules! textprop_reactive {
88    ($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) =>
89    {
90        #[allow(deprecated)]
91        impl<$($gen),*> From<$name<$($gen),*>> for TextProp
92        where
93            $v: Into<Oco<'static, str>>  + Clone + Send + Sync + 'static,
94            $($where_clause)*
95        {
96            #[inline(always)]
97            fn from(s: $name<$($gen),*>) -> Self {
98                TextProp(Arc::new(move || s.get().into()))
99            }
100        }
101    };
102}
103
104#[cfg(not(all(feature = "nightly", rustc_nightly)))]
105mod stable {
106    use super::TextProp;
107    use oco_ref::Oco;
108    #[allow(deprecated)]
109    use reactive_graph::wrappers::read::MaybeSignal;
110    use reactive_graph::{
111        computed::{ArcMemo, Memo},
112        owner::Storage,
113        signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
114        traits::Get,
115        wrappers::read::{ArcSignal, Signal},
116    };
117    use std::sync::Arc;
118
119    textprop_reactive!(
120        RwSignal,
121        <V, S>,
122        V,
123        RwSignal<V, S>: Get<Value = V>,
124        S: Storage<V> + Storage<Option<V>>,
125        S: Send + Sync + 'static,
126    );
127    textprop_reactive!(
128        ReadSignal,
129        <V, S>,
130        V,
131        ReadSignal<V, S>: Get<Value = V>,
132        S: Storage<V> + Storage<Option<V>>,
133        S: Send + Sync + 'static,
134    );
135    textprop_reactive!(
136        Memo,
137        <V, S>,
138        V,
139        Memo<V, S>: Get<Value = V>,
140        S: Storage<V> + Storage<Option<V>>,
141        S: Send + Sync + 'static,
142    );
143    textprop_reactive!(
144        Signal,
145        <V, S>,
146        V,
147        Signal<V, S>: Get<Value = V>,
148        S: Storage<V> + Storage<Option<V>>,
149        S: Send + Sync + 'static,
150    );
151    textprop_reactive!(
152        MaybeSignal,
153        <V, S>,
154        V,
155        MaybeSignal<V, S>: Get<Value = V>,
156        S: Storage<V> + Storage<Option<V>>,
157        S: Send + Sync + 'static,
158    );
159    textprop_reactive!(ArcRwSignal, <V>, V, ArcRwSignal<V>: Get<Value = V>);
160    textprop_reactive!(ArcReadSignal, <V>, V, ArcReadSignal<V>: Get<Value = V>);
161    textprop_reactive!(ArcMemo, <V>, V, ArcMemo<V>: Get<Value = V>);
162    textprop_reactive!(ArcSignal, <V>, V, ArcSignal<V>: Get<Value = V>);
163}
164
165/// Extension trait for `Option<TextProp>`
166pub trait OptionTextPropExt {
167    /// Accesses the current value of the `Option<TextProp>` as an `Option<Oco<'static, str>>`.
168    fn get(&self) -> Option<Oco<'static, str>>;
169}
170
171impl OptionTextPropExt for Option<TextProp> {
172    fn get(&self) -> Option<Oco<'static, str>> {
173        self.as_ref().map(|text_prop| text_prop.get())
174    }
175}