Skip to main content

euv_core/vdom/node/
enum.rs

1use super::*;
2
3/// Represents the type of an HTML tag or a component.
4///
5/// Distinguishes between standard HTML elements and user-defined components.
6///
7/// OPT 2: tag names are `Cow<'static, str>`. The `html!` macro emits
8/// `Cow::Borrowed("div")` for the common static case so a single
9/// static-string slice is reused across every rendered tree without
10/// per-element heap allocation. Runtime-derived tags (rare — only
11/// used by `Tag::Portal` whose `target:` is a user expression) fall
12/// back to `Cow::Owned(String::from(expr))`.
13#[derive(Clone, Debug, Eq, Hash, PartialEq)]
14pub enum Tag {
15    /// A standard HTML element identified by its tag name.
16    Element(Cow<'static, str>),
17    /// A custom component type.
18    Component(Cow<'static, str>),
19    /// A portal placeholder whose children are rendered into a
20    /// different DOM subtree than the rest of the virtual DOM.
21    ///
22    /// The payload is a CSS selector (`"#modal-root"`,
23    /// `"body"`, `".toast-host"`) identifying the destination
24    /// element. The renderer resolves the selector at mount time
25    /// via `document.query_selector(...)`, falling back to
26    /// `document.body()` when the selector matches nothing.
27    ///
28    /// Portal nodes render an HTML comment marker in their
29    /// declared position so the parent's DOM tree stays
30    /// structurally intact (the alternative — leaving a hole in
31    /// the parent — breaks euv's positional patch loop, which
32    /// walks child nodes by index).
33    ///
34    /// Patch semantics:
35    ///
36    /// - When the target selector is unchanged between renders,
37    ///   the portal's children are patched in place inside the
38    ///   target element.
39    /// - When the target selector changes, the previous target's
40    ///   children are unmounted and the new target receives a
41    ///   fresh mount.
42    ///
43    /// Designed for modals, tooltips, dropdowns, and, toasts —
44    /// UI that needs to escape `overflow: hidden` parents and
45    /// sit at the document root regardless of where it was
46    /// declared in the virtual DOM.
47    Portal(Cow<'static, str>),
48}
49
50/// Represents a node in the virtual DOM tree.
51///
52/// The core enum representing elements, text, fragments, and empty nodes.
53/// The generic parameter `T` carries the component props type for component nodes.
54/// For non-component nodes, `T` defaults to `()`.
55pub enum VirtualNode<T = ()> {
56    /// An element node with a tag, attributes, children, and optional props.
57    Element {
58        /// The tag type of this element.
59        tag: Tag,
60        /// The attributes attached to this element.
61        attributes: Vec<AttributeEntry>,
62        /// The child nodes.
63        children: Vec<VirtualNode>,
64        /// An optional key for diffing.
65        key: Option<String>,
66        /// The component props, present only for component nodes.
67        props: Option<Box<T>>,
68    },
69    /// A text node containing string content and an optional reactive signal.
70    Text(TextNode),
71    /// A fragment of multiple nodes without a wrapper element.
72    Fragment(Vec<VirtualNode>),
73    /// A dynamic node that re-renders based on signal changes.
74    Dynamic(DynamicNode),
75    /// An empty placeholder node.
76    Empty,
77}