1use oco_ref::Oco;
2use std::sync::Arc;
3use tachys::prelude::IntoAttributeValue;
4
5#[derive(Clone)]
8pub struct TextProp(Arc<dyn Fn() -> Oco<'static, str> + Send + Sync>);
9
10impl TextProp {
11 #[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
51impl<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
164pub trait OptionTextPropExt {
166 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}