silkenweb/
dom.rs

1//! An abstraction for the underlying DOM.
2//!
3//! An application, or parts of an application, can be parameterized on the
4//! underlying DOM type so it can be rendered in different ways:
5//!
6//! - Server side rendering with [`Dry`]
7//! - Client side rendering with [`Wet`]
8//! - Hydrating a server side rendered initial application state with [`Hydro`]
9//! - As a template, or part of a template, with [`Template`]
10//!
11//! See the concrete DOM types for some examples.
12use std::marker::PhantomData;
13
14use include_doc::function_body;
15use silkenweb_macros::cfg_browser;
16
17use self::{
18    dry::{DryElement, DryNode, DryText},
19    hydro::{HydroElement, HydroNode, HydroText},
20    template::{TemplateElement, TemplateNode, TemplateText},
21    wet::{WetElement, WetNode, WetText},
22};
23
24pub(super) mod private;
25
26mod dry;
27mod hydro;
28mod template;
29mod wet;
30
31/// The main DOM abstraction.
32///
33/// This is not user implementable.
34pub trait Dom: private::Dom {}
35
36/// A DOM that can be instantiated from a [`Template`] DOM.
37pub trait InstantiableDom: Dom + private::InstantiableDom {}
38
39/// The [`Dom`] type to which a node belongs.
40pub trait InDom {
41    type Dom: Dom;
42}
43
44#[cfg_browser(true)]
45/// The default DOM for the current platform.
46pub type DefaultDom = Wet;
47
48#[cfg_browser(false)]
49/// The default DOM for the current platform.
50pub type DefaultDom = Dry;
51
52/// A DOM that can only be rendered on the server
53///
54/// # Example
55///
56/// Type annotations have been provided for clarity, but the types can be
57/// inferred.
58///
59/// ```
60#[doc = function_body!("tests/doc/dom.rs", dry, [])]
61/// ```
62pub struct Dry;
63
64impl Dom for Dry {}
65
66impl private::Dom for Dry {
67    type Element = DryElement;
68    type Node = DryNode;
69    type Text = DryText;
70}
71
72impl InstantiableDom for Dry {}
73
74impl private::InstantiableDom for Dry {
75    type InstantiableElement = DryElement;
76    type InstantiableNode = DryNode;
77}
78
79/// A DOM that can be rendered on the client or hydrated onto an existing DOM
80/// element.
81///
82/// # Example
83///
84/// Type annotations have been provided for clarity, but the types can be
85/// inferred.
86///
87/// ```no_run
88#[doc = function_body!("tests/doc/dom.rs", hydro, [])]
89/// ```
90pub struct Hydro;
91
92impl Dom for Hydro {}
93
94impl private::Dom for Hydro {
95    type Element = HydroElement;
96    type Node = HydroNode;
97    type Text = HydroText;
98}
99
100impl InstantiableDom for Hydro {}
101
102impl private::InstantiableDom for Hydro {
103    type InstantiableElement = HydroElement;
104    type InstantiableNode = HydroNode;
105}
106
107/// A DOM that can only be rendered on the client.
108///
109/// # Example
110///
111/// Type annotations have been provided for clarity, but the types can be
112/// inferred.
113///
114/// ```no_run
115#[doc = function_body!("tests/doc/dom.rs", wet, [])]
116/// ```
117pub struct Wet;
118
119impl Dom for Wet {}
120
121impl private::Dom for Wet {
122    type Element = WetElement;
123    type Node = WetNode;
124    type Text = WetText;
125}
126
127impl InstantiableDom for Wet {}
128
129impl private::InstantiableDom for Wet {
130    type InstantiableElement = WetElement;
131    type InstantiableNode = WetNode;
132}
133
134/// A template DOM that can be used to instantiate other DOM types by cloning.
135///
136/// Cloning a template can be faster than creating each DOM node individually.
137/// It's likely to get a maximum 10-20% increase, so should only be used in hot
138/// code paths.
139///
140/// # Example
141///
142/// Type annotations have been provided for clarity, but the types can be
143/// inferred.
144///
145/// ```
146#[doc = function_body!("tests/doc/dom.rs", template, [])]
147/// ```
148pub struct Template<Param, D: InstantiableDom = DefaultDom>(PhantomData<(Param, D)>);
149
150impl<Param: 'static, D: InstantiableDom> Dom for Template<Param, D> {}
151
152impl<Param: 'static, D: InstantiableDom> private::Dom for Template<Param, D> {
153    type Element = TemplateElement<Param, D>;
154    type Node = TemplateNode<Param, D>;
155    type Text = TemplateText<D>;
156}