use serde::Serialize;
use super::signal::Signal;
use super::store::Store;
use super::view::{Child, Dynamic, View};
pub trait Component {
type Props: Clone + Send + Sync + 'static;
fn name() -> &'static str;
fn render(props: Self::Props) -> View;
}
#[allow(clippy::wrong_self_convention)]
pub trait IntoView {
fn into_view(&self) -> View;
}
impl IntoView for View {
fn into_view(&self) -> View {
self.clone()
}
}
impl IntoView for str {
fn into_view(&self) -> View {
View::text(self)
}
}
impl IntoView for String {
fn into_view(&self) -> View {
View::text(self.clone())
}
}
impl IntoView for &str {
fn into_view(&self) -> View {
View::text(*self)
}
}
macro_rules! impl_into_view_display {
($($t:ty),*) => {
$(
impl IntoView for $t {
fn into_view(&self) -> View { View::text(self.to_string()) }
}
)*
}
}
impl_into_view_display!(
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64, bool, char
);
impl<T: IntoView> IntoView for Option<T> {
fn into_view(&self) -> View {
match self {
Some(v) => v.into_view(),
None => View::empty(),
}
}
}
impl<T: IntoView> IntoView for Vec<T> {
fn into_view(&self) -> View {
let children: Vec<Child> = self.iter().map(|v| Child::View(v.into_view())).collect();
View::fragment(children)
}
}
impl<T: Clone + Serialize + 'static> IntoView for Signal<T> {
fn into_view(&self) -> View {
let snapshot = serde_json::to_value(self.peek()).unwrap_or(serde_json::Value::Null);
View::Dynamic(Dynamic {
signal: self.id(),
format: None,
snapshot,
})
}
}
impl<T: Clone + Serialize + 'static> IntoView for &Signal<T> {
fn into_view(&self) -> View {
(*self).into_view()
}
}
impl<T: Clone + Serialize + for<'de> serde::Deserialize<'de> + 'static> IntoView for Store<T> {
fn into_view(&self) -> View {
self.signal().into_view()
}
}
impl<T: Clone + Serialize + for<'de> serde::Deserialize<'de> + 'static> IntoView for &Store<T> {
fn into_view(&self) -> View {
self.signal().into_view()
}
}