Archived
feat: port el-ui vessels — rename crates→vessels, add El source + manifests
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
//! Web backend — DOM rendering in browsers.
|
||||
//!
|
||||
//! This backend formalizes what `runtime/src/renderer.js` does, as a Rust
|
||||
//! description of the DOM patching strategy. In a WASM build, this would call
|
||||
//! into the browser's DOM API directly via `web-sys`.
|
||||
|
||||
use crate::{EventHandler, PlatformBackend, PlatformError, PlatformNode, PlatformResult};
|
||||
|
||||
/// Web DOM backend.
|
||||
///
|
||||
/// Renders component trees to the browser DOM. In this Rust implementation,
|
||||
/// `render_to_string` produces an HTML string (matching what the JS renderer
|
||||
/// does for its initial hydration pass). A full WASM build would instead
|
||||
/// call `document.createElement()` etc. via `web-sys`.
|
||||
pub struct WebBackend;
|
||||
|
||||
impl WebBackend {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for WebBackend {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformBackend for WebBackend {
|
||||
fn name(&self) -> &'static str {
|
||||
"web"
|
||||
}
|
||||
|
||||
fn create_element(&self, tag: &str) -> PlatformResult<PlatformNode> {
|
||||
Ok(PlatformNode::element(tag))
|
||||
}
|
||||
|
||||
fn create_text(&self, content: &str) -> PlatformResult<PlatformNode> {
|
||||
Ok(PlatformNode::text(content))
|
||||
}
|
||||
|
||||
fn set_attribute(
|
||||
&self,
|
||||
node: &mut PlatformNode,
|
||||
name: &str,
|
||||
value: &str,
|
||||
) -> PlatformResult<()> {
|
||||
// Remove existing attribute with same name then push new one.
|
||||
node.attributes.retain(|a| a.name != name);
|
||||
node.attributes.push(crate::Attribute::new(name, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_attribute(&self, node: &mut PlatformNode, name: &str) -> PlatformResult<()> {
|
||||
node.attributes.retain(|a| a.name != name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn append_child(
|
||||
&self,
|
||||
parent: &mut PlatformNode,
|
||||
child: PlatformNode,
|
||||
) -> PlatformResult<()> {
|
||||
parent.children.push(child);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_child(&self, parent: &mut PlatformNode, child_index: usize) -> PlatformResult<()> {
|
||||
if child_index >= parent.children.len() {
|
||||
return Err(PlatformError::Render(format!(
|
||||
"web: child index {} out of bounds (len {})",
|
||||
child_index,
|
||||
parent.children.len()
|
||||
)));
|
||||
}
|
||||
parent.children.remove(child_index);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn replace_child(
|
||||
&self,
|
||||
parent: &mut PlatformNode,
|
||||
index: usize,
|
||||
new_child: PlatformNode,
|
||||
) -> PlatformResult<()> {
|
||||
if index >= parent.children.len() {
|
||||
return Err(PlatformError::Render(format!(
|
||||
"web: replace_child index {} out of bounds",
|
||||
index
|
||||
)));
|
||||
}
|
||||
parent.children[index] = new_child;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bind_event(
|
||||
&self,
|
||||
node: &mut PlatformNode,
|
||||
event: &str,
|
||||
_handler: EventHandler,
|
||||
) -> PlatformResult<()> {
|
||||
// In a real WASM build: node.add_event_listener_with_callback(event, &closure)
|
||||
// Here we record the binding in a data attribute so the JS renderer can pick it up.
|
||||
node.attributes
|
||||
.push(crate::Attribute::new(format!("data-el-{}", event), "[bound]"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_to_string(&self, node: &PlatformNode) -> PlatformResult<String> {
|
||||
Ok(node.to_html())
|
||||
}
|
||||
|
||||
fn mount(&self, _root: PlatformNode, _container_id: &str) -> PlatformResult<()> {
|
||||
// In a real WASM build:
|
||||
// let container = document.query_selector(container_id)?;
|
||||
// container.set_inner_html(&root.to_html());
|
||||
// For the Rust-side representation, mount is a no-op.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn patch(&self, _old: &PlatformNode, _new: &PlatformNode) -> PlatformResult<()> {
|
||||
// Full DOM patching mirrors renderer.js patch():
|
||||
// 1. Walk old and new trees in parallel.
|
||||
// 2. For each position: if node kinds differ, replace; else update attributes.
|
||||
// 3. Recurse into children.
|
||||
// In a WASM build this calls web-sys DOM mutation APIs.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn supports_ssr(&self) -> bool {
|
||||
// Web backend can produce HTML strings for hydration.
|
||||
true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user