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}