1use std::{any::Any, borrow::Cow, collections::HashMap, rc::Rc};
2use wasm_bindgen::JsValue;
3
4use crate::PassedToJsRuntime;
5
6#[derive(Debug, Clone, Default)]
7pub struct AnyJsProps {
8 pub js_props_without_children: Option<js_sys::Object>,
9 pub children: Option<crate::Children>,
10}
11
12impl AnyJsPropsBuilder for AnyJsProps {
13 #[inline]
14 fn set_prop(&mut self, name: &str, value: &JsValue) -> &mut Self {
15 let obj = self
16 .js_props_without_children
17 .get_or_insert_with(|| js_sys::Object::new());
18 js_sys::Reflect::set(obj.as_ref(), &JsValue::from_str(name), &value).unwrap();
19
20 self
21 }
22
23 #[inline]
24 fn set_children(&mut self, children: Option<crate::Children>) -> &mut Self {
25 self.children = children;
26 self
27 }
28
29 #[inline]
30 fn remove_prop(&mut self, name: &str) -> &mut Self {
31 let obj = self
32 .js_props_without_children
33 .get_or_insert_with(|| js_sys::Object::new());
34 js_sys::Reflect::delete_property(obj.as_ref(), &JsValue::from_str(name)).unwrap();
35
36 self
37 }
38}
39
40pub trait AnyJsPropsBuilder {
41 fn set_prop(&mut self, name: &str, value: &JsValue) -> &mut Self;
42 fn remove_prop(&mut self, name: &str) -> &mut Self;
43 fn set_children(&mut self, children: Option<crate::Children>) -> &mut Self;
44}
45
46#[derive(Debug, Default, Clone)]
47pub struct AnyJsStaticPropsPersistedValue(HashMap<Cow<'static, str>, Rc<dyn Any>>);
48
49impl AnyJsStaticPropsPersistedValue {
50 pub fn replace_static(&mut self, name: &'static str, value: Rc<dyn Any>) {
51 self.0.insert(Cow::Borrowed(name), value);
52 }
53 pub fn replace(&mut self, name: String, value: Rc<dyn Any>) {
54 self.0.insert(Cow::Owned(name), value);
55 }
56 pub fn remove(&mut self, name: &str) {
57 self.0.remove(name);
58 }
59}
60
61#[derive(Debug, Default, Clone)]
62pub struct AnyJsStaticProps {
63 pub props: AnyJsProps,
64 pub persisted: AnyJsStaticPropsPersistedValue,
65}
66
67impl AnyJsStaticProps {
68 #[inline]
69 pub fn set_static_prop_and_persist(
70 &mut self,
71 name: &'static str,
72 value: PassedToJsRuntime,
73 ) -> &mut Self {
74 self.props.set_prop(name, &value.js_value);
75 if let Some(p) = value.to_persist {
76 self.persisted.replace_static(name, p.into());
77 } else {
78 self.persisted.remove(name);
79 }
80 self
81 }
82}
83
84impl AnyJsPropsBuilder for AnyJsStaticProps {
85 #[inline]
86 fn set_prop(&mut self, name: &str, value: &JsValue) -> &mut Self {
87 self.props.set_prop(name, value);
88 self.persisted.remove(name);
89 self
90 }
91
92 #[inline]
93 fn set_children(&mut self, children: Option<crate::Children>) -> &mut Self {
94 self.props.set_children(children);
95 self
96 }
97
98 fn remove_prop(&mut self, name: &str) -> &mut Self {
99 self.props.remove_prop(name);
100 self.persisted.remove(name);
101
102 self
103 }
104}
105
106impl crate::Props for AnyJsProps {
107 type InitialBuilder = Self;
108
109 #[inline]
110 fn init_builder() -> Self::InitialBuilder {
111 Default::default()
112 }
113}
114
115impl crate::Props for AnyJsStaticProps {
116 type InitialBuilder = Self;
117
118 #[inline]
119 fn init_builder() -> Self::InitialBuilder {
120 Default::default()
121 }
122}
123
124impl crate::PropsBuilder<Self> for AnyJsProps {
125 #[inline]
126 fn build(self) -> Self {
127 self
128 }
129}
130
131impl crate::PropsBuilder<Self> for AnyJsStaticProps {
132 #[inline]
133 fn build(self) -> Self {
134 self
135 }
136}