use std::ops::Deref;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::Node;
use crate::internal;
pub trait Mountable: 'static {
type Js: JsCast;
fn js(&self) -> &JsValue;
fn unmount(&self);
fn replace_with(&self, new: &JsValue);
}
pub trait Anchor {
type Js: JsCast;
type Target: Mountable;
fn anchor(&self) -> &Self::Target;
}
impl<T> Mountable for T
where
T: Anchor + 'static,
T::Target: Mountable,
{
type Js = T::Js;
fn js(&self) -> &JsValue {
self.anchor().js()
}
fn unmount(&self) {
self.anchor().unmount();
}
fn replace_with(&self, new: &JsValue) {
self.anchor().replace_with(new);
}
}
#[derive(Clone)]
#[repr(transparent)]
pub struct Fragment(Node);
impl From<Node> for Fragment {
fn from(node: Node) -> Self {
internal::fragment_decorate(&node);
Fragment(node)
}
}
impl AsRef<JsValue> for Fragment {
fn as_ref(&self) -> &JsValue {
self.0.as_ref()
}
}
pub trait Property<Abi> {
fn set(self, this: &Node, value: Abi);
}
pub(crate) struct TextContent;
impl Property<&str> for TextContent {
fn set(self, this: &Node, value: &str) {
internal::set_text(this, value)
}
}
impl Property<f64> for TextContent {
fn set(self, this: &Node, value: f64) {
internal::set_text_num(this, value)
}
}
impl Property<bool> for TextContent {
fn set(self, this: &Node, value: bool) {
internal::set_text_bool(this, value)
}
}
pub(crate) struct FragmentBuilder {
fragment: Fragment,
tail: Node,
}
impl FragmentBuilder {
pub fn new() -> Self {
let fragment = Fragment(internal::fragment());
let tail = internal::fragment_decorate(&fragment.0);
FragmentBuilder { fragment, tail }
}
pub fn append(&self, child: &JsValue) {
internal::append_before(&self.tail, child);
}
}
impl Deref for FragmentBuilder {
type Target = Fragment;
fn deref(&self) -> &Fragment {
&self.fragment
}
}
impl Mountable for Node {
type Js = Node;
fn js(&self) -> &JsValue {
self
}
fn unmount(&self) {
internal::unmount(self)
}
fn replace_with(&self, new: &JsValue) {
internal::replace(self, new)
}
}
impl Mountable for Fragment {
type Js = Node;
fn js(&self) -> &JsValue {
&self.0
}
fn unmount(&self) {
internal::fragment_unmount(&self.0)
}
fn replace_with(&self, new: &JsValue) {
internal::fragment_replace(&self.0, new)
}
}