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
86macro_rules! textprop_reactive {
87    ($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) =>
88    {
89        #[allow(deprecated)]
90        impl<$($gen),*> From<$name<$($gen),*>> for TextProp
91        where
92            $v: Into<Oco<'static, str>>  + Clone + Send + Sync + 'static,
93            $($where_clause)*
94        {
95            #[inline(always)]
96            fn from(s: $name<$($gen),*>) -> Self {
97                TextProp(Arc::new(move || s.get().into()))
98            }
99        }
100    };
101}
102
103#[cfg(not(feature = "nightly"))]
104mod stable {
105    use super::TextProp;
106    use oco_ref::Oco;
107    #[allow(deprecated)]
108    use reactive_graph::wrappers::read::MaybeSignal;
109    use reactive_graph::{
110        computed::{ArcMemo, Memo},
111        owner::Storage,
112        signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
113        traits::Get,
114        wrappers::read::{ArcSignal, Signal},
115    };
116    use std::sync::Arc;
117
118    textprop_reactive!(
119        RwSignal,
120        <V, S>,
121        V,
122        RwSignal<V, S>: Get<Value = V>,
123        S: Storage<V> + Storage<Option<V>>,
124        S: Send + Sync + 'static,
125    );
126    textprop_reactive!(
127        ReadSignal,
128        <V, S>,
129        V,
130        ReadSignal<V, S>: Get<Value = V>,
131        S: Storage<V> + Storage<Option<V>>,
132        S: Send + Sync + 'static,
133    );
134    textprop_reactive!(
135        Memo,
136        <V, S>,
137        V,
138        Memo<V, S>: Get<Value = V>,
139        S: Storage<V> + Storage<Option<V>>,
140        S: Send + Sync + 'static,
141    );
142    textprop_reactive!(
143        Signal,
144        <V, S>,
145        V,
146        Signal<V, S>: Get<Value = V>,
147        S: Storage<V> + Storage<Option<V>>,
148        S: Send + Sync + 'static,
149    );
150    textprop_reactive!(
151        MaybeSignal,
152        <V, S>,
153        V,
154        MaybeSignal<V, S>: Get<Value = V>,
155        S: Storage<V> + Storage<Option<V>>,
156        S: Send + Sync + 'static,
157    );
158    textprop_reactive!(ArcRwSignal, <V>, V, ArcRwSignal<V>: Get<Value = V>);
159    textprop_reactive!(ArcReadSignal, <V>, V, ArcReadSignal<V>: Get<Value = V>);
160    textprop_reactive!(ArcMemo, <V>, V, ArcMemo<V>: Get<Value = V>);
161    textprop_reactive!(ArcSignal, <V>, V, ArcSignal<V>: Get<Value = V>);
162}
163
164/// Extension trait for `Option<TextProp>`
165pub trait OptionTextPropExt {
166    /// Accesses the current value of the `Option<TextProp>` as an `Option<Oco<'static, str>>`.
167    fn get(&self) -> Option<Oco<'static, str>>;
168}
169
170impl OptionTextPropExt for Option<TextProp> {
171    fn get(&self) -> Option<Oco<'static, str>> {
172        self.as_ref().map(|text_prop| text_prop.get())
173    }
174}