This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/ui/vessels/el-platform/src/lib.rs
T

127 lines
4.4 KiB
Rust

//! el-platform — Universal rendering backends for el-ui.
//!
//! The same component code produces native output for every target platform.
//! No bridge. No virtual DOM. Direct platform calls.
//!
//! The target is chosen in `el.toml`:
//!
//! ```toml
//! [platform]
//! target = "web" # web | server | ios | android | macos | linux | windows
//! ssr = true
//! ```
//!
//! All platforms implement the `PlatformBackend` trait. A future agent fills in
//! the native API calls for iOS/Android/macOS/Linux/Windows — the architecture
//! is correct and complete now.
pub mod backends;
pub mod config;
pub mod node;
pub use backends::{
android::AndroidBackend,
ios::IosBackend,
linux::LinuxBackend,
macos::MacosBackend,
server::ServerBackend,
web::WebBackend,
windows::WindowsBackend,
};
pub use config::{PlatformConfig, PlatformTarget};
pub use node::{Attribute, EventHandler, PlatformNode, PlatformNodeKind};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum PlatformError {
#[error("render error: {0}")]
Render(String),
#[error("mount error: {0}")]
Mount(String),
#[error("unsupported operation on target {target}: {op}")]
Unsupported { target: String, op: String },
#[error("event binding error: {0}")]
EventBinding(String),
}
pub type PlatformResult<T> = Result<T, PlatformError>;
/// The core trait every platform backend must implement.
///
/// All rendering paths go through this interface. Component code is identical
/// across targets — only the backend chosen by `el.toml` differs.
pub trait PlatformBackend: Send + Sync {
/// The platform name (e.g. "web", "server", "ios").
fn name(&self) -> &'static str;
/// Create a new element node on this platform.
fn create_element(&self, tag: &str) -> PlatformResult<PlatformNode>;
/// Create a text node on this platform.
fn create_text(&self, content: &str) -> PlatformResult<PlatformNode>;
/// Set an attribute on a node.
fn set_attribute(&self, node: &mut PlatformNode, name: &str, value: &str)
-> PlatformResult<()>;
/// Remove an attribute from a node.
fn remove_attribute(&self, node: &mut PlatformNode, name: &str) -> PlatformResult<()>;
/// Append a child node to a parent.
fn append_child(&self, parent: &mut PlatformNode, child: PlatformNode)
-> PlatformResult<()>;
/// Remove a child node from a parent.
fn remove_child(&self, parent: &mut PlatformNode, child_index: usize) -> PlatformResult<()>;
/// Replace a child node at the given index.
fn replace_child(
&self,
parent: &mut PlatformNode,
index: usize,
new_child: PlatformNode,
) -> PlatformResult<()>;
/// Bind an event handler to a node.
fn bind_event(
&self,
node: &mut PlatformNode,
event: &str,
handler: EventHandler,
) -> PlatformResult<()>;
/// Render a node tree to its platform representation.
/// For `server`, this returns an HTML string.
/// For `web`, this patches the live DOM.
/// For native targets, this calls the appropriate native APIs.
fn render_to_string(&self, node: &PlatformNode) -> PlatformResult<String>;
/// Mount a node tree into the platform's root container.
/// `container_id` is a platform-specific identifier (CSS selector for web,
/// view controller ID for iOS, activity ID for Android, etc.).
fn mount(&self, root: PlatformNode, container_id: &str) -> PlatformResult<()>;
/// Patch an existing mounted tree with a new tree.
/// The backend performs the minimal update needed.
fn patch(&self, old: &PlatformNode, new: &PlatformNode) -> PlatformResult<()>;
/// Whether this backend supports SSR (rendering to HTML string on the server).
fn supports_ssr(&self) -> bool {
false
}
}
/// Select the backend for a given platform target.
pub fn backend_for(target: &PlatformTarget) -> Box<dyn PlatformBackend> {
match target {
PlatformTarget::Web => Box::new(WebBackend::new()),
PlatformTarget::Server => Box::new(ServerBackend::new()),
PlatformTarget::Ios => Box::new(IosBackend::new()),
PlatformTarget::Android => Box::new(AndroidBackend::new()),
PlatformTarget::Macos => Box::new(MacosBackend::new()),
PlatformTarget::Linux => Box::new(LinuxBackend::new()),
PlatformTarget::Windows => Box::new(WindowsBackend::new()),
}
}