#![deny(missing_debug_implementations)]
mod dom_node;
mod dom_node_template;
#[cfg(feature = "hydrate")]
pub mod hydrate;
#[cfg(feature = "hydrate")]
mod hydrate_node;
#[cfg(feature = "ssr")]
mod ssr_node;
use std::cell::Cell;
use std::rc::Rc;
pub use dom_node::*;
#[cfg(feature = "hydrate")]
pub use hydrate_node::*;
use once_cell::sync::Lazy;
#[cfg(feature = "ssr")]
pub use ssr_node::*;
use sycamore_core::generic_node::{GenericNode, GenericNodeElements};
use sycamore_reactive::*;
use wasm_bindgen::prelude::*;
pub trait Html:
GenericNode<AnyEventData = JsValue, PropertyType = JsValue> + GenericNodeElements
{
const IS_BROWSER: bool;
fn to_web_sys(&self) -> web_sys::Node;
fn from_web_sys(node: web_sys::Node) -> Self;
}
static VOID_ELEMENTS: Lazy<hashbrown::HashSet<&'static str>> = Lazy::new(|| {
vec![
"area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param",
"source", "track", "wbr", "command", "keygen", "menuitem",
]
.into_iter()
.collect()
});
pub fn on_mount(f: impl FnOnce() + 'static) {
if cfg!(target_arch = "wasm32") {
let is_alive = Rc::new(Cell::new(true));
on_cleanup({
let is_alive = Rc::clone(&is_alive);
move || is_alive.set(false)
});
let scope = use_current_scope();
let cb = move || {
if is_alive.get() {
scope.run_in(f);
}
};
queue_microtask(cb);
}
}
pub fn queue_microtask(f: impl FnOnce() + 'static) {
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = "queueMicrotask")]
fn queue_microtask_js(f: &JsValue);
}
queue_microtask_js(&Closure::once_into_js(f));
}
pub(crate) fn document() -> web_sys::Document {
thread_local! {
static DOCUMENT: web_sys::Document = web_sys::window().unwrap_throw().document().unwrap_throw();
};
DOCUMENT.with(|document| document.clone())
}