docs: add tachys docs
This commit is contained in:
parent
ddb596feb5
commit
64bc2580ff
|
@ -1,6 +1,5 @@
|
||||||
use once_cell::unsync::Lazy;
|
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use web_sys::{Document, HtmlElement, Node, Window};
|
use web_sys::{Document, HtmlElement, Window};
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
pub(crate) static WINDOW: web_sys::Window = web_sys::window().unwrap();
|
pub(crate) static WINDOW: web_sys::Window = web_sys::window().unwrap();
|
||||||
|
@ -20,27 +19,22 @@ pub fn window() -> Window {
|
||||||
///
|
///
|
||||||
/// This is cached as a thread-local variable, so calling `document()` multiple times
|
/// This is cached as a thread-local variable, so calling `document()` multiple times
|
||||||
/// requires only one call out to JavaScript.
|
/// requires only one call out to JavaScript.
|
||||||
|
///
|
||||||
|
/// ## Panics
|
||||||
|
/// Panics if called outside a browser environment.
|
||||||
pub fn document() -> Document {
|
pub fn document() -> Document {
|
||||||
DOCUMENT.with(Clone::clone)
|
DOCUMENT.with(Clone::clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `<body>` element.
|
||||||
|
///
|
||||||
|
/// ## Panics
|
||||||
|
/// Panics if there is no `<body>` in the current document, or if it is called outside a browser
|
||||||
|
/// environment.
|
||||||
pub fn body() -> HtmlElement {
|
pub fn body() -> HtmlElement {
|
||||||
document().body().unwrap()
|
document().body().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn comment() -> Node {
|
|
||||||
thread_local! {
|
|
||||||
static COMMENT: Lazy<Node> = Lazy::new(|| {
|
|
||||||
document().create_comment("").unchecked_into()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
COMMENT.with(|n| n.clone_node().unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn log(s: &str) {
|
|
||||||
web_sys::console::log_1(&wasm_bindgen::JsValue::from_str(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper function to extract [`Event.target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target)
|
/// Helper function to extract [`Event.target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target)
|
||||||
/// from any event.
|
/// from any event.
|
||||||
pub fn event_target<T>(event: &web_sys::Event) -> T
|
pub fn event_target<T>(event: &web_sys::Event) -> T
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::{
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
|
/// A type-erased container for any [`Attribute`].
|
||||||
pub struct AnyAttribute<R: Renderer> {
|
pub struct AnyAttribute<R: Renderer> {
|
||||||
type_id: TypeId,
|
type_id: TypeId,
|
||||||
html_len: usize,
|
html_len: usize,
|
||||||
|
@ -40,6 +41,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// View state for [`AnyAttribute`].
|
||||||
pub struct AnyAttributeState<R>
|
pub struct AnyAttributeState<R>
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
|
@ -50,10 +52,12 @@ where
|
||||||
rndr: PhantomData<R>,
|
rndr: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts an [`Attribute`] into [`AnyAttribute`].
|
||||||
pub trait IntoAnyAttribute<R>
|
pub trait IntoAnyAttribute<R>
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
{
|
{
|
||||||
|
/// Wraps the given attribute.
|
||||||
fn into_any_attr(self) -> AnyAttribute<R>;
|
fn into_any_attr(self) -> AnyAttribute<R>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,14 @@ use crate::{
|
||||||
view::add_attr::AddAnyAttr,
|
view::add_attr::AddAnyAttr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Applies ARIA attributes to an HTML element.
|
||||||
pub trait AriaAttributes<Rndr, V>
|
pub trait AriaAttributes<Rndr, V>
|
||||||
where
|
where
|
||||||
Self: Sized + AddAnyAttr<Rndr>,
|
Self: Sized + AddAnyAttr<Rndr>,
|
||||||
V: AttributeValue<Rndr>,
|
V: AttributeValue<Rndr>,
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
|
/// Identifies the currently active descendant of a composite widget.
|
||||||
fn aria_activedescendant(
|
fn aria_activedescendant(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -17,6 +19,7 @@ where
|
||||||
self.add_any_attr(aria_activedescendant(value))
|
self.add_any_attr(aria_activedescendant(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the `aria-relevant` attribute.
|
||||||
fn aria_atomic(
|
fn aria_atomic(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -24,6 +27,7 @@ where
|
||||||
self.add_any_attr(aria_atomic(value))
|
self.add_any_attr(aria_atomic(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether user input completion suggestions are provided.
|
||||||
fn aria_autocomplete(
|
fn aria_autocomplete(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -32,6 +36,7 @@ where
|
||||||
self.add_any_attr(aria_autocomplete(value))
|
self.add_any_attr(aria_autocomplete(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether an element, and its subtree, are currently being updated.
|
||||||
fn aria_busy(
|
fn aria_busy(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -39,6 +44,7 @@ where
|
||||||
self.add_any_attr(aria_busy(value))
|
self.add_any_attr(aria_busy(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates the current "checked" state of checkboxes, radio buttons, and other widgets.
|
||||||
fn aria_checked(
|
fn aria_checked(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -46,6 +52,7 @@ where
|
||||||
self.add_any_attr(aria_checked(value))
|
self.add_any_attr(aria_checked(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the number of columns in a table, grid, or treegrid.
|
||||||
fn aria_colcount(
|
fn aria_colcount(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -53,6 +60,7 @@ where
|
||||||
self.add_any_attr(aria_colcount(value))
|
self.add_any_attr(aria_colcount(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.
|
||||||
fn aria_colindex(
|
fn aria_colindex(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -60,6 +68,7 @@ where
|
||||||
self.add_any_attr(aria_colindex(value))
|
self.add_any_attr(aria_colindex(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid.
|
||||||
fn aria_colspan(
|
fn aria_colspan(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -67,6 +76,7 @@ where
|
||||||
self.add_any_attr(aria_colspan(value))
|
self.add_any_attr(aria_colspan(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identifies the element (or elements) whose contents or presence are controlled by the current element.
|
||||||
fn aria_controls(
|
fn aria_controls(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -74,6 +84,7 @@ where
|
||||||
self.add_any_attr(aria_controls(value))
|
self.add_any_attr(aria_controls(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates the element that represents the current item within a container or set of related elements.
|
||||||
fn aria_current(
|
fn aria_current(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -81,6 +92,7 @@ where
|
||||||
self.add_any_attr(aria_current(value))
|
self.add_any_attr(aria_current(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identifies the element (or elements) that describes the object.
|
||||||
fn aria_describedby(
|
fn aria_describedby(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -89,6 +101,7 @@ where
|
||||||
self.add_any_attr(aria_describedby(value))
|
self.add_any_attr(aria_describedby(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a string value that describes or annotates the current element.
|
||||||
fn aria_description(
|
fn aria_description(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -97,6 +110,7 @@ where
|
||||||
self.add_any_attr(aria_description(value))
|
self.add_any_attr(aria_description(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identifies the element that provides additional information related to the object.
|
||||||
fn aria_details(
|
fn aria_details(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -104,6 +118,7 @@ where
|
||||||
self.add_any_attr(aria_details(value))
|
self.add_any_attr(aria_details(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.
|
||||||
fn aria_disabled(
|
fn aria_disabled(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -111,6 +126,7 @@ where
|
||||||
self.add_any_attr(aria_disabled(value))
|
self.add_any_attr(aria_disabled(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates what functions can be performed when a dragged object is released on the drop target.
|
||||||
fn aria_dropeffect(
|
fn aria_dropeffect(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -118,6 +134,7 @@ where
|
||||||
self.add_any_attr(aria_dropeffect(value))
|
self.add_any_attr(aria_dropeffect(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the element that provides an error message related to the object.
|
||||||
fn aria_errormessage(
|
fn aria_errormessage(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -126,6 +143,7 @@ where
|
||||||
self.add_any_attr(aria_errormessage(value))
|
self.add_any_attr(aria_errormessage(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
|
||||||
fn aria_expanded(
|
fn aria_expanded(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -133,6 +151,7 @@ where
|
||||||
self.add_any_attr(aria_expanded(value))
|
self.add_any_attr(aria_expanded(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identifies the next element (or elements) in an alternate reading order of content.
|
||||||
fn aria_flowto(
|
fn aria_flowto(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -140,6 +159,7 @@ where
|
||||||
self.add_any_attr(aria_flowto(value))
|
self.add_any_attr(aria_flowto(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates an element's "grabbed" state in a drag-and-drop operation.
|
||||||
fn aria_grabbed(
|
fn aria_grabbed(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -147,6 +167,7 @@ where
|
||||||
self.add_any_attr(aria_grabbed(value))
|
self.add_any_attr(aria_grabbed(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
|
||||||
fn aria_haspopup(
|
fn aria_haspopup(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -154,6 +175,7 @@ where
|
||||||
self.add_any_attr(aria_haspopup(value))
|
self.add_any_attr(aria_haspopup(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether the element is exposed to an accessibility API.
|
||||||
fn aria_hidden(
|
fn aria_hidden(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -161,6 +183,7 @@ where
|
||||||
self.add_any_attr(aria_hidden(value))
|
self.add_any_attr(aria_hidden(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates the entered value does not conform to the format expected by the application.
|
||||||
fn aria_invalid(
|
fn aria_invalid(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -168,6 +191,7 @@ where
|
||||||
self.add_any_attr(aria_invalid(value))
|
self.add_any_attr(aria_invalid(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
|
||||||
fn aria_keyshortcuts(
|
fn aria_keyshortcuts(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -176,6 +200,7 @@ where
|
||||||
self.add_any_attr(aria_keyshortcuts(value))
|
self.add_any_attr(aria_keyshortcuts(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a string value that labels the current element.
|
||||||
fn aria_label(
|
fn aria_label(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -183,6 +208,7 @@ where
|
||||||
self.add_any_attr(aria_label(value))
|
self.add_any_attr(aria_label(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identifies the element (or elements) that labels the current element.
|
||||||
fn aria_labelledby(
|
fn aria_labelledby(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -190,6 +216,7 @@ where
|
||||||
self.add_any_attr(aria_labelledby(value))
|
self.add_any_attr(aria_labelledby(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
|
||||||
fn aria_live(
|
fn aria_live(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -197,6 +224,7 @@ where
|
||||||
self.add_any_attr(aria_live(value))
|
self.add_any_attr(aria_live(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether an element is modal when displayed.
|
||||||
fn aria_modal(
|
fn aria_modal(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -204,6 +232,7 @@ where
|
||||||
self.add_any_attr(aria_modal(value))
|
self.add_any_attr(aria_modal(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether a text box accepts multiple lines of input or only a single line.
|
||||||
fn aria_multiline(
|
fn aria_multiline(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -211,6 +240,7 @@ where
|
||||||
self.add_any_attr(aria_multiline(value))
|
self.add_any_attr(aria_multiline(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates that the user may select more than one item from the current selectable descendants.
|
||||||
fn aria_multiselectable(
|
fn aria_multiselectable(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -219,6 +249,7 @@ where
|
||||||
self.add_any_attr(aria_multiselectable(value))
|
self.add_any_attr(aria_multiselectable(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates whether the element's orientation is horizontal, vertical, or undefined.
|
||||||
fn aria_orientation(
|
fn aria_orientation(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -227,6 +258,7 @@ where
|
||||||
self.add_any_attr(aria_orientation(value))
|
self.add_any_attr(aria_orientation(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship.
|
||||||
fn aria_owns(
|
fn aria_owns(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -234,6 +266,7 @@ where
|
||||||
self.add_any_attr(aria_owns(value))
|
self.add_any_attr(aria_owns(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a short hint (a word or short phrase) intended to help the user with data entry when the control has no value.
|
||||||
fn aria_placeholder(
|
fn aria_placeholder(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -242,6 +275,7 @@ where
|
||||||
self.add_any_attr(aria_placeholder(value))
|
self.add_any_attr(aria_placeholder(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines an element's number or position in the current set of listitems or treeitems.
|
||||||
fn aria_posinset(
|
fn aria_posinset(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -249,6 +283,7 @@ where
|
||||||
self.add_any_attr(aria_posinset(value))
|
self.add_any_attr(aria_posinset(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates the current "pressed" state of toggle buttons.
|
||||||
fn aria_pressed(
|
fn aria_pressed(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -256,6 +291,7 @@ where
|
||||||
self.add_any_attr(aria_pressed(value))
|
self.add_any_attr(aria_pressed(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates that the element is not editable, but is otherwise operable.
|
||||||
fn aria_readonly(
|
fn aria_readonly(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -263,6 +299,7 @@ where
|
||||||
self.add_any_attr(aria_readonly(value))
|
self.add_any_attr(aria_readonly(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified.
|
||||||
fn aria_relevant(
|
fn aria_relevant(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -270,6 +307,7 @@ where
|
||||||
self.add_any_attr(aria_relevant(value))
|
self.add_any_attr(aria_relevant(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates that user input is required on the element before a form may be submitted.
|
||||||
fn aria_required(
|
fn aria_required(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -277,6 +315,7 @@ where
|
||||||
self.add_any_attr(aria_required(value))
|
self.add_any_attr(aria_required(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a human-readable, author-localized description for the role of an element.
|
||||||
fn aria_roledescription(
|
fn aria_roledescription(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -285,6 +324,7 @@ where
|
||||||
self.add_any_attr(aria_roledescription(value))
|
self.add_any_attr(aria_roledescription(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the total number of rows in a table, grid, or treegrid.
|
||||||
fn aria_rowcount(
|
fn aria_rowcount(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -292,6 +332,7 @@ where
|
||||||
self.add_any_attr(aria_rowcount(value))
|
self.add_any_attr(aria_rowcount(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid.
|
||||||
fn aria_rowindex(
|
fn aria_rowindex(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -299,6 +340,7 @@ where
|
||||||
self.add_any_attr(aria_rowindex(value))
|
self.add_any_attr(aria_rowindex(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.
|
||||||
fn aria_rowspan(
|
fn aria_rowspan(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -306,6 +348,7 @@ where
|
||||||
self.add_any_attr(aria_rowspan(value))
|
self.add_any_attr(aria_rowspan(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates the current "selected" state of various widgets.
|
||||||
fn aria_selected(
|
fn aria_selected(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -313,6 +356,7 @@ where
|
||||||
self.add_any_attr(aria_selected(value))
|
self.add_any_attr(aria_selected(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the number of items in the current set of listitems or treeitems.
|
||||||
fn aria_setsize(
|
fn aria_setsize(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -320,6 +364,7 @@ where
|
||||||
self.add_any_attr(aria_setsize(value))
|
self.add_any_attr(aria_setsize(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates if items in a table or grid are sorted in ascending or descending order.
|
||||||
fn aria_sort(
|
fn aria_sort(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -327,6 +372,7 @@ where
|
||||||
self.add_any_attr(aria_sort(value))
|
self.add_any_attr(aria_sort(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the maximum allowed value for a range widget.
|
||||||
fn aria_valuemax(
|
fn aria_valuemax(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -334,6 +380,7 @@ where
|
||||||
self.add_any_attr(aria_valuemax(value))
|
self.add_any_attr(aria_valuemax(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the minimum allowed value for a range widget.
|
||||||
fn aria_valuemin(
|
fn aria_valuemin(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -341,6 +388,7 @@ where
|
||||||
self.add_any_attr(aria_valuemin(value))
|
self.add_any_attr(aria_valuemin(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the current value for a range widget.
|
||||||
fn aria_valuenow(
|
fn aria_valuenow(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -348,6 +396,7 @@ where
|
||||||
self.add_any_attr(aria_valuenow(value))
|
self.add_any_attr(aria_valuenow(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the human-readable text alternative of `aria-valuenow` for a range widget.
|
||||||
fn aria_valuetext(
|
fn aria_valuetext(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::{borrow::Cow, marker::PhantomData, sync::Arc};
|
use std::{borrow::Cow, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
|
/// Adds a custom attribute with any key-value combintion.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn custom_attribute<K, V, R>(key: K, value: V) -> CustomAttr<K, V, R>
|
pub fn custom_attribute<K, V, R>(key: K, value: V) -> CustomAttr<K, V, R>
|
||||||
where
|
where
|
||||||
|
@ -20,6 +21,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A custom attribute with any key-value combination.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CustomAttr<K, V, R>
|
pub struct CustomAttr<K, V, R>
|
||||||
where
|
where
|
||||||
|
@ -154,7 +156,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this needs to be a method, not a const
|
// TODO this needs to be a method, not a const
|
||||||
|
/// Defines a custom attribute key.
|
||||||
pub trait CustomAttributeKey: Clone + AsRef<str> + Send + 'static {
|
pub trait CustomAttributeKey: Clone + AsRef<str> + Send + 'static {
|
||||||
|
/// The attribute name.
|
||||||
const KEY: &'static str;
|
const KEY: &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +185,7 @@ impl<const K: &'static str> CustomAttributeKey
|
||||||
const KEY: &'static str = K;
|
const KEY: &'static str = K;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a custom attribute to an element.
|
||||||
pub trait CustomAttribute<K, V, Rndr>
|
pub trait CustomAttribute<K, V, Rndr>
|
||||||
where
|
where
|
||||||
K: CustomAttributeKey,
|
K: CustomAttributeKey,
|
||||||
|
@ -188,6 +193,7 @@ where
|
||||||
Rndr: DomRenderer,
|
Rndr: DomRenderer,
|
||||||
Self: Sized + AddAnyAttr<Rndr>,
|
Self: Sized + AddAnyAttr<Rndr>,
|
||||||
{
|
{
|
||||||
|
/// Adds an HTML attribute by key and value.
|
||||||
fn attr(
|
fn attr(
|
||||||
self,
|
self,
|
||||||
key: K,
|
key: K,
|
||||||
|
|
|
@ -13,13 +13,16 @@ use crate::{
|
||||||
};
|
};
|
||||||
use core::convert::From;
|
use core::convert::From;
|
||||||
|
|
||||||
|
/// Adds an attribute that modifies the `class`.
|
||||||
pub trait ClassAttribute<C, Rndr>
|
pub trait ClassAttribute<C, Rndr>
|
||||||
where
|
where
|
||||||
C: IntoClass<Rndr>,
|
C: IntoClass<Rndr>,
|
||||||
Rndr: DomRenderer,
|
Rndr: DomRenderer,
|
||||||
{
|
{
|
||||||
|
/// The type of the element with the new attribute added.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Adds a CSS class to an element.
|
||||||
fn class(self, value: C) -> Self::Output;
|
fn class(self, value: C) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,13 +39,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds an attribute that modifies the DOM properties.
|
||||||
pub trait PropAttribute<K, P, Rndr>
|
pub trait PropAttribute<K, P, Rndr>
|
||||||
where
|
where
|
||||||
P: IntoProperty<Rndr>,
|
P: IntoProperty<Rndr>,
|
||||||
Rndr: DomRenderer,
|
Rndr: DomRenderer,
|
||||||
{
|
{
|
||||||
|
/// The type of the element with the new attribute added.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Adds a DOM property to an element.
|
||||||
fn prop(self, key: K, value: P) -> Self::Output;
|
fn prop(self, key: K, value: P) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,18 +60,22 @@ where
|
||||||
Rndr: DomRenderer,
|
Rndr: DomRenderer,
|
||||||
{
|
{
|
||||||
type Output = <Self as AddAnyAttr<Rndr>>::Output<Property<K, P, Rndr>>;
|
type Output = <Self as AddAnyAttr<Rndr>>::Output<Property<K, P, Rndr>>;
|
||||||
|
|
||||||
fn prop(self, key: K, value: P) -> Self::Output {
|
fn prop(self, key: K, value: P) -> Self::Output {
|
||||||
self.add_any_attr(prop(key, value))
|
self.add_any_attr(prop(key, value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds an attribute that modifies the CSS styles.
|
||||||
pub trait StyleAttribute<S, Rndr>
|
pub trait StyleAttribute<S, Rndr>
|
||||||
where
|
where
|
||||||
S: IntoStyle<Rndr>,
|
S: IntoStyle<Rndr>,
|
||||||
Rndr: DomRenderer,
|
Rndr: DomRenderer,
|
||||||
{
|
{
|
||||||
|
/// The type of the element with the new attribute added.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Adds a CSS style to an element.
|
||||||
fn style(self, value: S) -> Self::Output;
|
fn style(self, value: S) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +92,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds an event listener to an element definition.
|
||||||
pub trait OnAttribute<E, F, Rndr> {
|
pub trait OnAttribute<E, F, Rndr> {
|
||||||
|
/// The type of the element with the event listener added.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Adds an event listener to an element.
|
||||||
fn on(self, event: E, cb: F) -> Self::Output;
|
fn on(self, event: E, cb: F) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +117,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds an event listener with a typed target to an element definition.
|
||||||
pub trait OnTargetAttribute<E, F, T, Rndr> {
|
pub trait OnTargetAttribute<E, F, T, Rndr> {
|
||||||
|
/// The type of the element with the new attribute added.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Adds an event listener with a typed target to an element definition.
|
||||||
fn on_target(self, event: E, cb: F) -> Self::Output;
|
fn on_target(self, event: E, cb: F) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,12 +146,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Global attributes can be added to any HTML element.
|
||||||
pub trait GlobalAttributes<Rndr, V>
|
pub trait GlobalAttributes<Rndr, V>
|
||||||
where
|
where
|
||||||
Self: Sized + AddAnyAttr<Rndr>,
|
Self: Sized + AddAnyAttr<Rndr>,
|
||||||
V: AttributeValue<Rndr>,
|
V: AttributeValue<Rndr>,
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
|
/// The `accesskey` global attribute provides a hint for generating a keyboard shortcut for the current element.
|
||||||
fn accesskey(
|
fn accesskey(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -143,6 +161,7 @@ where
|
||||||
self.add_any_attr(accesskey(value))
|
self.add_any_attr(accesskey(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `autocapitalize` global attribute controls whether and how text input is automatically capitalized as it is entered/edited by the user.
|
||||||
fn autocapitalize(
|
fn autocapitalize(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -150,6 +169,7 @@ where
|
||||||
self.add_any_attr(autocapitalize(value))
|
self.add_any_attr(autocapitalize(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `autofocus` global attribute is a Boolean attribute indicating that an element should receive focus as soon as the page is loaded.
|
||||||
fn autofocus(
|
fn autofocus(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -157,6 +177,7 @@ where
|
||||||
self.add_any_attr(autofocus(value))
|
self.add_any_attr(autofocus(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `contenteditable` global attribute is an enumerated attribute indicating if the element should be editable by the user.
|
||||||
fn contenteditable(
|
fn contenteditable(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -165,6 +186,7 @@ where
|
||||||
self.add_any_attr(contenteditable(value))
|
self.add_any_attr(contenteditable(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `dir` global attribute is an enumerated attribute indicating the directionality of the element's text.
|
||||||
fn dir(
|
fn dir(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -172,6 +194,7 @@ where
|
||||||
self.add_any_attr(dir(value))
|
self.add_any_attr(dir(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `draggable` global attribute is an enumerated attribute indicating whether the element can be dragged.
|
||||||
fn draggable(
|
fn draggable(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -179,6 +202,7 @@ where
|
||||||
self.add_any_attr(draggable(value))
|
self.add_any_attr(draggable(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `enterkeyhint` global attribute is used to customize the enter key on virtual keyboards.
|
||||||
fn enterkeyhint(
|
fn enterkeyhint(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -186,6 +210,7 @@ where
|
||||||
self.add_any_attr(enterkeyhint(value))
|
self.add_any_attr(enterkeyhint(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `hidden` global attribute is a Boolean attribute indicating that the element is not yet, or is no longer, relevant.
|
||||||
fn hidden(
|
fn hidden(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -193,6 +218,7 @@ where
|
||||||
self.add_any_attr(hidden(value))
|
self.add_any_attr(hidden(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `id` global attribute defines a unique identifier (ID) which must be unique in the whole document.
|
||||||
fn id(
|
fn id(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -200,6 +226,7 @@ where
|
||||||
self.add_any_attr(id(value))
|
self.add_any_attr(id(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `inert` global attribute is a Boolean attribute that makes an element behave inertly.
|
||||||
fn inert(
|
fn inert(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -207,6 +234,7 @@ where
|
||||||
self.add_any_attr(inert(value))
|
self.add_any_attr(inert(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `inputmode` global attribute provides a hint to browsers for which virtual keyboard to display.
|
||||||
fn inputmode(
|
fn inputmode(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -214,6 +242,7 @@ where
|
||||||
self.add_any_attr(inputmode(value))
|
self.add_any_attr(inputmode(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `is` global attribute allows you to specify that a standard HTML element should behave like a custom built-in element.
|
||||||
fn is(
|
fn is(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -221,6 +250,7 @@ where
|
||||||
self.add_any_attr(is(value))
|
self.add_any_attr(is(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `itemid` global attribute is used to specify the unique, global identifier of an item.
|
||||||
fn itemid(
|
fn itemid(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -228,6 +258,7 @@ where
|
||||||
self.add_any_attr(itemid(value))
|
self.add_any_attr(itemid(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `itemprop` global attribute is used to add properties to an item.
|
||||||
fn itemprop(
|
fn itemprop(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -235,6 +266,7 @@ where
|
||||||
self.add_any_attr(itemprop(value))
|
self.add_any_attr(itemprop(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `itemref` global attribute is used to refer to other elements.
|
||||||
fn itemref(
|
fn itemref(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -242,6 +274,7 @@ where
|
||||||
self.add_any_attr(itemref(value))
|
self.add_any_attr(itemref(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `itemscope` global attribute is used to create a new item.
|
||||||
fn itemscope(
|
fn itemscope(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -249,6 +282,7 @@ where
|
||||||
self.add_any_attr(itemscope(value))
|
self.add_any_attr(itemscope(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `itemtype` global attribute is used to specify the types of items.
|
||||||
fn itemtype(
|
fn itemtype(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -256,6 +290,7 @@ where
|
||||||
self.add_any_attr(itemtype(value))
|
self.add_any_attr(itemtype(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `lang` global attribute helps define the language of an element.
|
||||||
fn lang(
|
fn lang(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -263,6 +298,7 @@ where
|
||||||
self.add_any_attr(lang(value))
|
self.add_any_attr(lang(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `nonce` global attribute is used to specify a cryptographic nonce.
|
||||||
fn nonce(
|
fn nonce(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -270,6 +306,7 @@ where
|
||||||
self.add_any_attr(nonce(value))
|
self.add_any_attr(nonce(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `part` global attribute identifies the element as a part of a component.
|
||||||
fn part(
|
fn part(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -277,6 +314,7 @@ where
|
||||||
self.add_any_attr(part(value))
|
self.add_any_attr(part(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `popover` global attribute defines the popover's behavior.
|
||||||
fn popover(
|
fn popover(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -284,6 +322,7 @@ where
|
||||||
self.add_any_attr(popover(value))
|
self.add_any_attr(popover(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `role` global attribute defines the role of an element in ARIA.
|
||||||
fn role(
|
fn role(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -291,6 +330,7 @@ where
|
||||||
self.add_any_attr(role(value))
|
self.add_any_attr(role(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `slot` global attribute assigns a slot in a shadow DOM.
|
||||||
fn slot(
|
fn slot(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -298,6 +338,7 @@ where
|
||||||
self.add_any_attr(slot(value))
|
self.add_any_attr(slot(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `spellcheck` global attribute is an enumerated attribute that defines whether the element may be checked for spelling errors.
|
||||||
fn spellcheck(
|
fn spellcheck(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -305,6 +346,7 @@ where
|
||||||
self.add_any_attr(spellcheck(value))
|
self.add_any_attr(spellcheck(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `tabindex` global attribute indicates if the element can take input focus.
|
||||||
fn tabindex(
|
fn tabindex(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -312,6 +354,7 @@ where
|
||||||
self.add_any_attr(tabindex(value))
|
self.add_any_attr(tabindex(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `title` global attribute contains text representing advisory information.
|
||||||
fn title(
|
fn title(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -319,6 +362,7 @@ where
|
||||||
self.add_any_attr(title(value))
|
self.add_any_attr(title(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `translate` global attribute is an enumerated attribute that specifies whether an element's attribute values and text content should be translated when the page is localized.
|
||||||
fn translate(
|
fn translate(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
@ -326,6 +370,7 @@ where
|
||||||
self.add_any_attr(translate(value))
|
self.add_any_attr(translate(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `virtualkeyboardpolicy` global attribute specifies the behavior of the virtual keyboard.
|
||||||
fn virtualkeyboardpolicy(
|
fn virtualkeyboardpolicy(
|
||||||
self,
|
self,
|
||||||
value: V,
|
value: V,
|
||||||
|
|
|
@ -2,14 +2,18 @@ use super::{Attr, AttributeValue};
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use std::{fmt::Debug, marker::PhantomData};
|
use std::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
|
/// An HTML attribute key.
|
||||||
pub trait AttributeKey: Clone + Send + 'static {
|
pub trait AttributeKey: Clone + Send + 'static {
|
||||||
|
/// The name of the attribute.
|
||||||
const KEY: &'static str;
|
const KEY: &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! attributes {
|
macro_rules! attributes {
|
||||||
($($key:ident $html:literal),* $(,)?) => {
|
($(#[$meta:meta] $key:ident $html:literal),* $(,)?) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
$(
|
$(
|
||||||
|
#[$meta]
|
||||||
|
#[track_caller]
|
||||||
pub fn $key<V, Rndr>(value: V) -> Attr<[<$key:camel>], V, Rndr>
|
pub fn $key<V, Rndr>(value: V) -> Attr<[<$key:camel>], V, Rndr>
|
||||||
where V: AttributeValue<Rndr>,
|
where V: AttributeValue<Rndr>,
|
||||||
Rndr: Renderer
|
Rndr: Renderer
|
||||||
|
@ -17,6 +21,7 @@ macro_rules! attributes {
|
||||||
Attr([<$key:camel>], value, PhantomData)
|
Attr([<$key:camel>], value, PhantomData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[$meta]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct [<$key:camel>];
|
pub struct [<$key:camel>];
|
||||||
|
|
||||||
|
@ -28,311 +33,618 @@ macro_rules! attributes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO attribute names with underscores should be kebab-cased
|
|
||||||
attributes! {
|
attributes! {
|
||||||
// HTML
|
// HTML
|
||||||
abbr "abbr", // [],
|
/// The `abbr` attribute specifies an abbreviated form of the element's content.
|
||||||
accept_charset "accept-charset", // [],
|
abbr "abbr",
|
||||||
accept "accept", // [],
|
/// The `accept-charset` attribute specifies the character encodings that are to be used for the form submission.
|
||||||
accesskey "accesskey", // [], // [GlobalAttribute]
|
accept_charset "accept-charset",
|
||||||
action "action", // [],
|
/// The `accept` attribute specifies a list of types the server accepts, typically a file type.
|
||||||
align "align", // [],
|
accept "accept",
|
||||||
allow "allow", // [],
|
/// The `accesskey` attribute specifies a shortcut key to activate or focus an element.
|
||||||
allowfullscreen "allowfullscreen", // [],
|
accesskey "accesskey",
|
||||||
allowpaymentrequest "allowpaymentrequest", // [],
|
/// The `action` attribute defines the URL to which the form data will be sent.
|
||||||
alt "alt", // [],
|
action "action",
|
||||||
|
/// The `align` attribute specifies the alignment of an element.
|
||||||
|
align "align",
|
||||||
|
/// The `allow` attribute defines a feature policy for the content in an iframe.
|
||||||
|
allow "allow",
|
||||||
|
/// The `allowfullscreen` attribute allows the iframe to be displayed in fullscreen mode.
|
||||||
|
allowfullscreen "allowfullscreen",
|
||||||
|
/// The `allowpaymentrequest` attribute allows a cross-origin iframe to invoke the Payment Request API.
|
||||||
|
allowpaymentrequest "allowpaymentrequest",
|
||||||
|
/// The `alt` attribute provides alternative text for an image, if the image cannot be displayed.
|
||||||
|
alt "alt",
|
||||||
// ARIA
|
// ARIA
|
||||||
|
/// The `aria-activedescendant` attribute identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
|
||||||
aria_activedescendant "aria-activedescendant",
|
aria_activedescendant "aria-activedescendant",
|
||||||
aria_atomic "aria-atomic", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-atomic` attribute indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
|
||||||
|
aria_atomic "aria-atomic",
|
||||||
|
/// The `aria-autocomplete` attribute indicates whether user input completion suggestions are provided.
|
||||||
aria_autocomplete "aria-autocomplete",
|
aria_autocomplete "aria-autocomplete",
|
||||||
aria_busy "aria-busy", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-busy` attribute indicates whether an element, and its subtree, are currently being updated.
|
||||||
|
aria_busy "aria-busy",
|
||||||
|
/// The `aria-checked` attribute indicates the current "checked" state of checkboxes, radio buttons, and other widgets.
|
||||||
aria_checked "aria-checked",
|
aria_checked "aria-checked",
|
||||||
|
/// The `aria-colcount` attribute defines the total number of columns in a table, grid, or treegrid.
|
||||||
aria_colcount "aria-colcount",
|
aria_colcount "aria-colcount",
|
||||||
|
/// The `aria-colindex` attribute defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.
|
||||||
aria_colindex "aria-colindex",
|
aria_colindex "aria-colindex",
|
||||||
|
/// The `aria-colspan` attribute defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid.
|
||||||
aria_colspan "aria-colspan",
|
aria_colspan "aria-colspan",
|
||||||
aria_controls "aria-controls", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-controls` attribute identifies the element (or elements) whose contents or presence are controlled by the current element.
|
||||||
aria_current "aria-current", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_controls "aria-controls",
|
||||||
aria_describedby "aria-describedby", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-current` attribute indicates the element representing the current item within a container or set of related elements.
|
||||||
aria_description "aria-description", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_current "aria-current",
|
||||||
aria_details "aria-details", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-describedby` attribute identifies the element (or elements) that describes the object.
|
||||||
aria_disabled "aria-disabled", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_describedby "aria-describedby",
|
||||||
aria_dropeffect "aria-dropeffect", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-description` attribute provides a string value that describes or annotates the current element.
|
||||||
aria_errormessage "aria-errormessage", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_description "aria-description",
|
||||||
|
/// The `aria-details` attribute identifies the element that provides a detailed, extended description for the object.
|
||||||
|
aria_details "aria-details",
|
||||||
|
/// The `aria-disabled` attribute indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.
|
||||||
|
aria_disabled "aria-disabled",
|
||||||
|
/// The `aria-dropeffect` attribute indicates what functions can be performed when a dragged object is released on the drop target.
|
||||||
|
aria_dropeffect "aria-dropeffect",
|
||||||
|
/// The `aria-errormessage` attribute identifies the element that provides an error message for the object.
|
||||||
|
aria_errormessage "aria-errormessage",
|
||||||
|
/// The `aria-expanded` attribute indicates whether an element, or another grouping element it controls, is currently expanded or collapsed.
|
||||||
aria_expanded "aria-expanded",
|
aria_expanded "aria-expanded",
|
||||||
aria_flowto "aria-flowto", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-flowto` attribute identifies the next element (or elements) in an alternate reading order of content.
|
||||||
aria_grabbed "aria-grabbed", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_flowto "aria-flowto",
|
||||||
aria_haspopup "aria-haspopup", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-grabbed` attribute indicates an element's "grabbed" state in a drag-and-drop operation.
|
||||||
aria_hidden "aria-hidden", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_grabbed "aria-grabbed",
|
||||||
aria_invalid "aria-invalid", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-haspopup` attribute indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
|
||||||
aria_keyshortcuts "aria-keyshortcuts", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_haspopup "aria-haspopup",
|
||||||
aria_label "aria-label", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-hidden` attribute indicates whether the element is exposed to an accessibility API.
|
||||||
aria_labelledby "aria-labelledby", // [], // [GlobalAttribute] // [AriaAttribute],
|
aria_hidden "aria-hidden",
|
||||||
aria_live "aria-live", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-invalid` attribute indicates the entered value does not conform to the format expected by the application.
|
||||||
|
aria_invalid "aria-invalid",
|
||||||
|
/// The `aria-keyshortcuts` attribute indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
|
||||||
|
aria_keyshortcuts "aria-keyshortcuts",
|
||||||
|
/// The `aria-label` attribute defines a string value that labels the current element.
|
||||||
|
aria_label "aria-label",
|
||||||
|
/// The `aria-labelledby` attribute identifies the element (or elements) that labels the current element.
|
||||||
|
aria_labelledby "aria-labelledby",
|
||||||
|
/// The `aria-live` attribute indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
|
||||||
|
aria_live "aria-live",
|
||||||
|
/// The `aria-modal` attribute indicates whether an element is modal when displayed.
|
||||||
aria_modal "aria-modal",
|
aria_modal "aria-modal",
|
||||||
|
/// The `aria-multiline` attribute indicates whether a text box accepts multiple lines of input or only a single line.
|
||||||
aria_multiline "aria-multiline",
|
aria_multiline "aria-multiline",
|
||||||
|
/// The `aria-multiselectable` attribute indicates that the user may select more than one item from the current selectable descendants.
|
||||||
aria_multiselectable "aria-multiselectable",
|
aria_multiselectable "aria-multiselectable",
|
||||||
|
/// The `aria-orientation` attribute indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
|
||||||
aria_orientation "aria-orientation",
|
aria_orientation "aria-orientation",
|
||||||
aria_owns "aria-owns", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-owns` attribute identifies an element (or elements) in order to define a relationship between the element with `aria-owns` and the target element.
|
||||||
|
aria_owns "aria-owns",
|
||||||
|
/// The `aria-placeholder` attribute defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.
|
||||||
aria_placeholder "aria-placeholder",
|
aria_placeholder "aria-placeholder",
|
||||||
|
/// The `aria-posinset` attribute defines an element's position within a set or treegrid.
|
||||||
aria_posinset "aria-posinset",
|
aria_posinset "aria-posinset",
|
||||||
|
/// The `aria-pressed` attribute indicates the current "pressed" state of toggle buttons.
|
||||||
aria_pressed "aria-pressed",
|
aria_pressed "aria-pressed",
|
||||||
|
/// The `aria-readonly` attribute indicates that the element is not editable, but is otherwise operable.
|
||||||
aria_readonly "aria-readonly",
|
aria_readonly "aria-readonly",
|
||||||
aria_relevant "aria-relevant", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-relevant` attribute indicates what user agent changes to the accessibility tree should be monitored.
|
||||||
|
aria_relevant "aria-relevant",
|
||||||
|
/// The `aria-required` attribute indicates that user input is required on the element before a form may be submitted.
|
||||||
aria_required "aria-required",
|
aria_required "aria-required",
|
||||||
aria_roledescription "aria-roledescription", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `aria-roledescription` attribute defines a human-readable, author-localized description for the role of an element.
|
||||||
|
aria_roledescription "aria-roledescription",
|
||||||
|
/// The `aria-rowcount` attribute defines the total number of rows in a table, grid, or treegrid.
|
||||||
aria_rowcount "aria-rowcount",
|
aria_rowcount "aria-rowcount",
|
||||||
|
/// The `aria-rowindex` attribute defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid.
|
||||||
aria_rowindex "aria-rowindex",
|
aria_rowindex "aria-rowindex",
|
||||||
|
/// The `aria-rowspan` attribute defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.
|
||||||
aria_rowspan "aria-rowspan",
|
aria_rowspan "aria-rowspan",
|
||||||
|
/// The `aria-selected` attribute indicates the current "selected" state of various widgets.
|
||||||
aria_selected "aria-selected",
|
aria_selected "aria-selected",
|
||||||
|
/// The `aria-setsize` attribute defines the number of items in the current set of listitems or treeitems.
|
||||||
aria_setsize "aria-setsize",
|
aria_setsize "aria-setsize",
|
||||||
|
/// The `aria-sort` attribute indicates if items in a table or grid are sorted in ascending or descending order.
|
||||||
aria_sort "aria-sort",
|
aria_sort "aria-sort",
|
||||||
|
/// The `aria-valuemax` attribute defines the maximum allowed value for a range widget.
|
||||||
aria_valuemax "aria-valuemax",
|
aria_valuemax "aria-valuemax",
|
||||||
|
/// The `aria-valuemin` attribute defines the minimum allowed value for a range widget.
|
||||||
aria_valuemin "aria-valuemin",
|
aria_valuemin "aria-valuemin",
|
||||||
|
/// The `aria-valuenow` attribute defines the current value for a range widget.
|
||||||
aria_valuenow "aria-valuenow",
|
aria_valuenow "aria-valuenow",
|
||||||
|
/// The `aria-valuetext` attribute defines the human-readable text alternative of aria-valuenow for a range widget.
|
||||||
aria_valuetext "aria-valuetext",
|
aria_valuetext "aria-valuetext",
|
||||||
r#as "as", // [],
|
/// The `as` attribute specifies the type of destination for the content of the link.
|
||||||
r#async "async", // [],
|
r#as "as",
|
||||||
autocapitalize "autocapitalize", // [], // [GlobalAttribute]
|
/// The `async` attribute indicates that the script should be executed asynchronously.
|
||||||
autocomplete "autocomplete", // [],
|
r#async "async",
|
||||||
autofocus "autofocus", // [], // [GlobalAttribute]
|
/// The `autocapitalize` attribute controls whether and how text input is automatically capitalized as it is entered/edited by the user.
|
||||||
autoplay "autoplay", // [],
|
autocapitalize "autocapitalize",
|
||||||
background "background", // [],
|
/// The `autocomplete` attribute indicates whether an input field can have its value automatically completed by the browser.
|
||||||
bgcolor "bgcolor", // [],
|
autocomplete "autocomplete",
|
||||||
blocking "blocking", // [],
|
/// The `autofocus` attribute indicates that an element should be focused on page load.
|
||||||
border "border", // [],
|
autofocus "autofocus",
|
||||||
buffered "buffered", // [],
|
/// The `autoplay` attribute indicates that the media should start playing as soon as it is loaded.
|
||||||
capture "capture", // [],
|
autoplay "autoplay",
|
||||||
challenge "challenge", // [],
|
/// The `background` attribute sets the URL of the background image for the document.
|
||||||
charset "charset", // [],
|
background "background",
|
||||||
checked "checked", // [],
|
/// The `bgcolor` attribute sets the background color of an element.
|
||||||
cite "cite", // [],
|
bgcolor "bgcolor",
|
||||||
|
/// The `blocking` attribute indicates that the script will block the page loading until it is executed.
|
||||||
|
blocking "blocking",
|
||||||
|
/// The `border` attribute sets the width of an element's border.
|
||||||
|
border "border",
|
||||||
|
/// The `buffered` attribute contains the time ranges that the media has been buffered.
|
||||||
|
buffered "buffered",
|
||||||
|
/// The `capture` attribute indicates that the user must capture media using a camera or microphone instead of selecting a file from the file picker.
|
||||||
|
capture "capture",
|
||||||
|
/// The `challenge` attribute specifies the challenge string that is paired with the keygen element.
|
||||||
|
challenge "challenge",
|
||||||
|
/// The `charset` attribute specifies the character encoding of the HTML document.
|
||||||
|
charset "charset",
|
||||||
|
/// The `checked` attribute indicates whether an input element is checked or not.
|
||||||
|
checked "checked",
|
||||||
|
/// The `cite` attribute contains a URL that points to the source of the quotation or change.
|
||||||
|
cite "cite",
|
||||||
// class is handled in ../class.rs instead
|
// class is handled in ../class.rs instead
|
||||||
//class "class", // [],
|
//class "class",
|
||||||
code "code", // [],
|
/// The `code` attribute specifies the URL of the applet's class file to be loaded and executed.
|
||||||
color "color", // [],
|
code "code",
|
||||||
cols "cols", // [],
|
/// The `color` attribute specifies the color of an element's text.
|
||||||
colspan "colspan", // [],
|
color "color",
|
||||||
content "content", // [],
|
/// The `cols` attribute specifies the visible width of a text area.
|
||||||
contenteditable "contenteditable", // [], // [GlobalAttribute]
|
cols "cols",
|
||||||
contextmenu "contextmenu", // [], // [GlobalAttribute]
|
/// The `colspan` attribute defines the number of columns a cell should span.
|
||||||
controls "controls", // [],
|
colspan "colspan",
|
||||||
controlslist "controlslist", // [],
|
/// The `content` attribute gives the value associated with the http-equiv or name attribute.
|
||||||
coords "coords", // [],
|
content "content",
|
||||||
crossorigin "crossorigin", // [],
|
/// The `contenteditable` attribute indicates whether the element's content is editable.
|
||||||
csp "csp", // [],
|
contenteditable "contenteditable",
|
||||||
data "data", // [],
|
/// The `contextmenu` attribute specifies the ID of a `<menu>` element to open as a context menu.
|
||||||
datetime "datetime", // [],
|
contextmenu "contextmenu",
|
||||||
decoding "decoding", // [],
|
/// The `controls` attribute indicates whether the browser should display playback controls for the media.
|
||||||
default "default", // [],
|
controls "controls",
|
||||||
defer "defer", // [],
|
/// The `controlslist` attribute allows the control of which controls to show on the media element whenever the browser shows its native controls.
|
||||||
dir "dir", // [], // [GlobalAttribute]
|
controlslist "controlslist",
|
||||||
dirname "dirname", // [],
|
/// The `coords` attribute specifies the coordinates of an area in an image map.
|
||||||
disabled "disabled", // [],
|
coords "coords",
|
||||||
disablepictureinpicture "disablepictureinpicture", // [],
|
/// The `crossorigin` attribute indicates whether the resource should be fetched with a CORS request.
|
||||||
disableremoteplayback "disableremoteplayback", // [],
|
crossorigin "crossorigin",
|
||||||
download "download", // [],
|
/// The `csp` attribute allows the embedding document to define the Content Security Policy that an embedded document must agree to enforce upon itself.
|
||||||
draggable "draggable", // [], // [GlobalAttribute]
|
csp "csp",
|
||||||
enctype "enctype", // [],
|
/// The `data` attribute specifies the URL of the resource that is being embedded.
|
||||||
enterkeyhint "enterkeyhint", // [], // [GlobalAttribute]
|
data "data",
|
||||||
exportparts "exportparts", // [], // [GlobalAttribute]
|
/// The `datetime` attribute specifies the date and time.
|
||||||
fetchpriority "fetchprioty", // [],
|
datetime "datetime",
|
||||||
r#for "for", // [],
|
/// The `decoding` attribute indicates the preferred method for decoding images.
|
||||||
form "form", // [],
|
decoding "decoding",
|
||||||
formaction "formaction", // [],
|
/// The `default` attribute indicates that the track should be enabled unless the user's preferences indicate that another track is more appropriate.
|
||||||
formenctype "formenctype", // [],
|
default "default",
|
||||||
formmethod "formmethod", // [],
|
/// The `defer` attribute indicates that the script should be executed after the document has been parsed.
|
||||||
formnovalidate "formnovalidate", // [],
|
defer "defer",
|
||||||
formtarget "formtarget", // [],
|
/// The `dir` attribute specifies the text direction for the content in an element.
|
||||||
headers "headers", // [],
|
dir "dir",
|
||||||
height "height", // [],
|
/// The `dirname` attribute identifies the text directionality of an input element.
|
||||||
hidden "hidden", // [], // [GlobalAttribute]
|
dirname "dirname",
|
||||||
high "high", // [],
|
/// The `disabled` attribute indicates whether the element is disabled.
|
||||||
href "href", // [],
|
disabled "disabled",
|
||||||
hreflang "hreflang", // [],
|
/// The `disablepictureinpicture` attribute indicates that the element is not allowed to be displayed in Picture-in-Picture mode.
|
||||||
http_equiv "http-equiv", // [],
|
disablepictureinpicture "disablepictureinpicture",
|
||||||
icon "icon", // [],
|
/// The `disableremoteplayback` attribute indicates that the element is not allowed to be displayed using remote playback.
|
||||||
id "id", // [], // [GlobalAttribute]
|
disableremoteplayback "disableremoteplayback",
|
||||||
|
/// The `download` attribute indicates that the linked resource is intended to be downloaded rather than displayed in the browser.
|
||||||
|
download "download",
|
||||||
|
/// The `draggable` attribute indicates whether the element is draggable.
|
||||||
|
draggable "draggable",
|
||||||
|
/// The `enctype` attribute specifies the MIME type of the form submission.
|
||||||
|
enctype "enctype",
|
||||||
|
/// The `enterkeyhint` attribute allows authors to specify what kind of action label or icon will be presented to users in a virtual keyboard's enter key.
|
||||||
|
enterkeyhint "enterkeyhint",
|
||||||
|
/// The `exportparts` attribute enables the sharing of parts of an element's shadow DOM with a containing document.
|
||||||
|
exportparts "exportparts",
|
||||||
|
/// The `fetchpriority` attribute allows developers to specify the priority of a resource fetch request.
|
||||||
|
fetchpriority "fetchpriority",
|
||||||
|
/// The `for` attribute specifies which form element a label is bound to.
|
||||||
|
r#for "for",
|
||||||
|
/// The `form` attribute associates the element with a form element.
|
||||||
|
form "form",
|
||||||
|
/// The `formaction` attribute specifies the URL that processes the form submission.
|
||||||
|
formaction "formaction",
|
||||||
|
/// The `formenctype` attribute specifies how the form data should be encoded when submitted.
|
||||||
|
formenctype "formenctype",
|
||||||
|
/// The `formmethod` attribute specifies the HTTP method to use when submitting the form.
|
||||||
|
formmethod "formmethod",
|
||||||
|
/// The `formnovalidate` attribute indicates that the form should not be validated when submitted.
|
||||||
|
formnovalidate "formnovalidate",
|
||||||
|
/// The `formtarget` attribute specifies where to display the response after submitting the form.
|
||||||
|
formtarget "formtarget",
|
||||||
|
/// The `headers` attribute specifies the headers associated with the element.
|
||||||
|
headers "headers",
|
||||||
|
/// The `height` attribute specifies the height of an element.
|
||||||
|
height "height",
|
||||||
|
/// The `hidden` attribute indicates that the element is not yet, or is no longer, relevant.
|
||||||
|
hidden "hidden",
|
||||||
|
/// The `high` attribute specifies the range that is considered to be a high value.
|
||||||
|
high "high",
|
||||||
|
/// The `href` attribute specifies the URL of a linked resource.
|
||||||
|
href "href",
|
||||||
|
/// The `hreflang` attribute specifies the language of the linked resource.
|
||||||
|
hreflang "hreflang",
|
||||||
|
/// The `http-equiv` attribute provides an HTTP header for the information/value of the content attribute.
|
||||||
|
http_equiv "http-equiv",
|
||||||
|
/// The `icon` attribute specifies the URL of an image to be used as a graphical icon for the element.
|
||||||
|
icon "icon",
|
||||||
|
/// The `id` attribute specifies a unique id for an element.
|
||||||
|
id "id",
|
||||||
|
/// The `imagesizes` attribute specifies image sizes for different page layouts.
|
||||||
imagesizes "imagesizes",
|
imagesizes "imagesizes",
|
||||||
|
/// The `imagesrcset` attribute specifies the URLs of multiple images to be used in different situations.
|
||||||
imagesrcset "imagesrcset",
|
imagesrcset "imagesrcset",
|
||||||
importance "importance", // [],
|
/// The `importance` attribute specifies the relative importance of the element.
|
||||||
inert "inert", // [], // [GlobalAttribute]
|
importance "importance",
|
||||||
inputmode "inputmode", // [], // [GlobalAttribute]
|
/// The `inert` attribute indicates that the element is non-interactive and won't be accessible to user interactions or assistive technologies.
|
||||||
integrity "integrity", // [],
|
inert "inert",
|
||||||
intrinsicsize "intrinsicsize", // [],
|
/// The `inputmode` attribute specifies the type of data that the user will enter.
|
||||||
is "is", // [], // [GlobalAttribute]
|
inputmode "inputmode",
|
||||||
ismap "ismap", // [],
|
/// The `integrity` attribute contains a hash value that the browser can use to verify that the resource hasn't been altered.
|
||||||
itemid "itemid", // [], // [GlobalAttribute]
|
integrity "integrity",
|
||||||
itemprop "itemprop", // [], // [GlobalAttribute]
|
/// The `intrinsicsize` attribute specifies the intrinsic size of an image or video.
|
||||||
itemref "itemref", // [], // [GlobalAttribute]
|
intrinsicsize "intrinsicsize",
|
||||||
itemscope "itemscope", // [], // [GlobalAttribute]
|
/// The `is` attribute allows you to specify the name of a custom element.
|
||||||
itemtype "itemtype", // [], // [GlobalAttribute]
|
is "is",
|
||||||
keytype "keytype", // [],
|
/// The `ismap` attribute indicates that the image is part of a server-side image map.
|
||||||
kind "kind", // [],
|
ismap "ismap",
|
||||||
label "label", // [],
|
/// The `itemid` attribute assigns a unique identifier to an item.
|
||||||
lang "lang", // [], // [GlobalAttribute]
|
itemid "itemid",
|
||||||
language "language", // [],
|
/// The `itemprop` attribute adds a property to an item.
|
||||||
list "list", // [],
|
itemprop "itemprop",
|
||||||
loading "loading", // [],
|
/// The `itemref` attribute provides a list of element IDs that have additional properties for the item.
|
||||||
r#loop "loop", // [],
|
itemref "itemref",
|
||||||
low "low", // [],
|
/// The `itemscope` attribute creates a new item and adds it to the page's items.
|
||||||
manifest "manifest", // [],
|
itemscope "itemscope",
|
||||||
max "max", // [],
|
/// The `itemtype` attribute specifies the type of an item.
|
||||||
maxlength "maxlength", // [],
|
itemtype "itemtype",
|
||||||
media "media", // [],
|
/// The `keytype` attribute specifies the type of key used by the `<keygen>` element.
|
||||||
method "method", // [],
|
keytype "keytype",
|
||||||
min "min", // [],
|
/// The `kind` attribute specifies the kind of text track.
|
||||||
minlength "minlength", // [],
|
kind "kind",
|
||||||
multiple "multiple", // [],
|
/// The `label` attribute provides a user-readable title for an element.
|
||||||
muted "muted", // [],
|
label "label",
|
||||||
name "name", // [],
|
/// The `lang` attribute specifies the language of the element's content.
|
||||||
nomodule "nomodule", // [],
|
lang "lang",
|
||||||
nonce "nonce", // [], // [GlobalAttribute]
|
/// The `language` attribute specifies the scripting language used for the script.
|
||||||
novalidate "novalidate", // [],
|
language "language",
|
||||||
open "open", // [],
|
/// The `list` attribute identifies a `<datalist>` element that contains pre-defined options for an `<input>` element.
|
||||||
optimum "optimum", // [],
|
list "list",
|
||||||
part "part", // [], // [GlobalAttribute]
|
/// The `loading` attribute indicates how the browser should load the image.
|
||||||
pattern "pattern", // [],
|
loading "loading",
|
||||||
ping "ping", // [],
|
/// The `loop` attribute indicates whether the media should start over again when it reaches the end.
|
||||||
placeholder "placeholder", // [],
|
r#loop "loop",
|
||||||
playsinline "playsinline", // [],
|
/// The `low` attribute specifies the range that is considered to be a low value.
|
||||||
popover "popover", // [], // [GlobalAttribute]
|
low "low",
|
||||||
|
/// The `manifest` attribute specifies the URL of a document's cache manifest.
|
||||||
|
manifest "manifest",
|
||||||
|
/// The `max` attribute specifies the maximum value for an input element.
|
||||||
|
max "max",
|
||||||
|
/// The `maxlength` attribute specifies the maximum number of characters that an input element can accept.
|
||||||
|
maxlength "maxlength",
|
||||||
|
/// The `media` attribute specifies what media/device the linked resource is optimized for.
|
||||||
|
media "media",
|
||||||
|
/// The `method` attribute specifies the HTTP method to use when submitting the form.
|
||||||
|
method "method",
|
||||||
|
/// The `min` attribute specifies the minimum value for an input element.
|
||||||
|
min "min",
|
||||||
|
/// The `minlength` attribute specifies the minimum number of characters that an input element can accept.
|
||||||
|
minlength "minlength",
|
||||||
|
/// The `multiple` attribute indicates whether the user can enter more than one value.
|
||||||
|
multiple "multiple",
|
||||||
|
/// The `muted` attribute indicates whether the audio will be initially silenced on page load.
|
||||||
|
muted "muted",
|
||||||
|
/// The `name` attribute specifies the name of the element.
|
||||||
|
name "name",
|
||||||
|
/// The `nomodule` attribute indicates that the script should not be executed in browsers that support ES modules.
|
||||||
|
nomodule "nomodule",
|
||||||
|
/// The `nonce` attribute provides a cryptographic nonce to ensure that a script or style is approved for execution.
|
||||||
|
nonce "nonce",
|
||||||
|
/// The `novalidate` attribute indicates that the form should not be validated when submitted.
|
||||||
|
novalidate "novalidate",
|
||||||
|
/// The `open` attribute indicates whether the details element is open or closed.
|
||||||
|
open "open",
|
||||||
|
/// The `optimum` attribute specifies the range that is considered to be an optimum value.
|
||||||
|
optimum "optimum",
|
||||||
|
/// The `part` attribute identifies the element as a shadow DOM part.
|
||||||
|
part "part",
|
||||||
|
/// The `pattern` attribute specifies a regular expression that the input element's value is checked against.
|
||||||
|
pattern "pattern",
|
||||||
|
/// The `ping` attribute contains a space-separated list of URLs to be notified if the user follows the hyperlink.
|
||||||
|
ping "ping",
|
||||||
|
/// The `placeholder` attribute provides a short hint that describes the expected value of the input element.
|
||||||
|
placeholder "placeholder",
|
||||||
|
/// The `playsinline` attribute indicates that the video should play inline in the element's playback area.
|
||||||
|
playsinline "playsinline",
|
||||||
|
/// The `popover` attribute indicates that an element is a popover and specifies the event that causes the popover to be shown.
|
||||||
|
popover "popover",
|
||||||
|
/// The `popovertarget` attribute specifies the ID of an element to toggle a popover.
|
||||||
popovertarget "popovertarget",
|
popovertarget "popovertarget",
|
||||||
|
/// The `popovertargetaction` attribute specifies the action that shows the popover.
|
||||||
popovertargetaction "popovertargetaction",
|
popovertargetaction "popovertargetaction",
|
||||||
poster "poster", // [],
|
/// The `poster` attribute specifies an image to be shown while the video is downloading or until the user hits the play button.
|
||||||
preload "preload", // [],
|
poster "poster",
|
||||||
radiogroup "radiogroup", // [],
|
/// The `preload` attribute specifies if and how the author thinks that the media file should be loaded when the page loads.
|
||||||
readonly "readonly", // [],
|
preload "preload",
|
||||||
referrerpolicy "referrerpolicy", // [],
|
/// The `radiogroup` attribute specifies the name of the group to which the element belongs.
|
||||||
rel "rel", // [],
|
radiogroup "radiogroup",
|
||||||
required "required", // [],
|
/// The `readonly` attribute indicates that the user cannot modify the value of the input element.
|
||||||
reversed "reversed", // [],
|
readonly "readonly",
|
||||||
role "role", // [], // [GlobalAttribute] // [AriaAttribute],
|
/// The `referrerpolicy` attribute specifies which referrer information to include with requests.
|
||||||
rows "rows", // [],
|
referrerpolicy "referrerpolicy",
|
||||||
rowspan "rowspan", // [],
|
/// The `rel` attribute specifies the relationship between the current document and the linked document.
|
||||||
sandbox "sandbox", // [],
|
rel "rel",
|
||||||
scope "scope", // [],
|
/// The `required` attribute indicates that the user must fill in the input element before submitting the form.
|
||||||
scoped "scoped", // [],
|
required "required",
|
||||||
selected "selected", // [],
|
/// The `reversed` attribute indicates that the list should be displayed in a descending order.
|
||||||
shape "shape", // [],
|
reversed "reversed",
|
||||||
size "size", // [],
|
/// The `role` attribute defines the role of an element in the context of a web application.
|
||||||
sizes "sizes", // [],
|
role "role",
|
||||||
slot "slot", // [], // [GlobalAttribute]
|
/// The `rows` attribute specifies the number of visible text lines for a text area.
|
||||||
span "span", // [],
|
rows "rows",
|
||||||
spellcheck "spellcheck", // [], // [GlobalAttribute]
|
/// The `rowspan` attribute defines the number of rows a cell should span.
|
||||||
src "src", // [],
|
rowspan "rowspan",
|
||||||
srcdoc "srcdoc", // [],
|
/// The `sandbox` attribute applies extra restrictions to the content in the `<iframe>`.
|
||||||
srclang "srclang", // [],
|
sandbox "sandbox",
|
||||||
srcset "srcset", // [],
|
/// The `scope` attribute specifies whether a header cell is a header for a column, row, or group of columns or rows.
|
||||||
start "start", // [],
|
scope "scope",
|
||||||
step "step", // [],
|
/// The `scoped` attribute indicates that the styles in a `<style>` element are scoped to the parent element.
|
||||||
|
scoped "scoped",
|
||||||
|
/// The `selected` attribute indicates that the option is selected.
|
||||||
|
selected "selected",
|
||||||
|
/// The `shape` attribute specifies the shape of the area.
|
||||||
|
shape "shape",
|
||||||
|
/// The `size` attribute specifies the width of the input element.
|
||||||
|
size "size",
|
||||||
|
/// The `sizes` attribute specifies the sizes of icons for visual media.
|
||||||
|
sizes "sizes",
|
||||||
|
/// The `slot` attribute assigns a slot to an element.
|
||||||
|
slot "slot",
|
||||||
|
/// The `span` attribute defines the number of columns in a `<colgroup>` or the number of rows in a `<rowgroup>`.
|
||||||
|
span "span",
|
||||||
|
/// The `spellcheck` attribute indicates whether spell checking is allowed for the element.
|
||||||
|
spellcheck "spellcheck",
|
||||||
|
/// The `src` attribute specifies the URL of the media resource.
|
||||||
|
src "src",
|
||||||
|
/// The `srcdoc` attribute specifies the HTML content of the page to show in the `<iframe>`.
|
||||||
|
srcdoc "srcdoc",
|
||||||
|
/// The `srclang` attribute specifies the language of the text track.
|
||||||
|
srclang "srclang",
|
||||||
|
/// The `srcset` attribute specifies the URLs of multiple images to be used in different situations.
|
||||||
|
srcset "srcset",
|
||||||
|
/// The `start` attribute specifies the start value of the list.
|
||||||
|
start "start",
|
||||||
|
/// The `step` attribute specifies the legal number intervals for an input element.
|
||||||
|
step "step",
|
||||||
// style is handled in ../style.rs instead
|
// style is handled in ../style.rs instead
|
||||||
// style "style", // [],
|
// style "style",
|
||||||
summary "summary", // [],
|
/// The `summary` attribute provides a summary of the content of the table.
|
||||||
tabindex "tabindex", // [], // [GlobalAttribute]
|
summary "summary",
|
||||||
target "target", // [],
|
/// The `tabindex` attribute specifies the tab order of an element.
|
||||||
title "title", // [], // [GlobalAttribute]
|
tabindex "tabindex",
|
||||||
translate "translate", // [], // [GlobalAttribute]
|
/// The `target` attribute specifies where to open the linked document.
|
||||||
r#type "type", // [],
|
target "target",
|
||||||
usemap "usemap", // [],
|
/// The `title` attribute provides additional information about an element.
|
||||||
value "value", // [],
|
title "title",
|
||||||
virtualkeyboardpolicy "virtualkeyboardpolicy", // [], // [GlobalAttribute]
|
/// The `translate` attribute specifies whether the content of an element should be translated or not.
|
||||||
width "width", // [],
|
translate "translate",
|
||||||
wrap "wrap", // [],
|
/// The `type` attribute specifies the type of the element.
|
||||||
|
r#type "type",
|
||||||
|
/// The `usemap` attribute specifies the image map to be used by an `<img>` element.
|
||||||
|
usemap "usemap",
|
||||||
|
/// The `value` attribute specifies the value of the element.
|
||||||
|
value "value",
|
||||||
|
/// The `virtualkeyboardpolicy` attribute controls the policy for virtual keyboards.
|
||||||
|
virtualkeyboardpolicy "virtualkeyboardpolicy",
|
||||||
|
/// The `width` attribute specifies the width of an element.
|
||||||
|
width "width",
|
||||||
|
/// The `wrap` attribute specifies how the text in a text area is to be wrapped when submitted in a form.
|
||||||
|
wrap "wrap",
|
||||||
// Event Handler Attributes
|
// Event Handler Attributes
|
||||||
onabort "onabort", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onabort` attribute specifies the event handler for the abort event.
|
||||||
onautocomplete "onautocomplete", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onabort "onabort",
|
||||||
onautocompleteerror "onautocompleteerror", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onautocomplete` attribute specifies the event handler for the autocomplete event.
|
||||||
onblur "onblur", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onautocomplete "onautocomplete",
|
||||||
oncancel "oncancel", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onautocompleteerror` attribute specifies the event handler for the autocompleteerror event.
|
||||||
oncanplay "oncanplay", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onautocompleteerror "onautocompleteerror",
|
||||||
oncanplaythrough "oncanplaythrough", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onblur` attribute specifies the event handler for the blur event.
|
||||||
onchange "onchange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onblur "onblur",
|
||||||
onclick "onclick", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `oncancel` attribute specifies the event handler for the cancel event.
|
||||||
onclose "onclose", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
oncancel "oncancel",
|
||||||
oncontextmenu "oncontextmenu", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `oncanplay` attribute specifies the event handler for the canplay event.
|
||||||
oncuechange "oncuechange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
oncanplay "oncanplay",
|
||||||
ondblclick "ondblclick", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `oncanplaythrough` attribute specifies the event handler for the canplaythrough event.
|
||||||
ondrag "ondrag", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
oncanplaythrough "oncanplaythrough",
|
||||||
ondragend "ondragend", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onchange` attribute specifies the event handler for the change event.
|
||||||
ondragenter "ondragenter", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onchange "onchange",
|
||||||
ondragleave "ondragleave", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onclick` attribute specifies the event handler for the click event.
|
||||||
ondragover "ondragover", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onclick "onclick",
|
||||||
ondragstart "ondragstart", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onclose` attribute specifies the event handler for the close event.
|
||||||
ondrop "ondrop", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onclose "onclose",
|
||||||
ondurationchange "ondurationchange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `oncontextmenu` attribute specifies the event handler for the contextmenu event.
|
||||||
onemptied "onemptied", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
oncontextmenu "oncontextmenu",
|
||||||
onended "onended", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `oncuechange` attribute specifies the event handler for the cuechange event.
|
||||||
onerror "onerror", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
oncuechange "oncuechange",
|
||||||
onfocus "onfocus", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondblclick` attribute specifies the event handler for the double click event.
|
||||||
oninput "oninput", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondblclick "ondblclick",
|
||||||
oninvalid "oninvalid", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondrag` attribute specifies the event handler for the drag event.
|
||||||
onkeydown "onkeydown", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondrag "ondrag",
|
||||||
onkeypress "onkeypress", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondragend` attribute specifies the event handler for the dragend event.
|
||||||
onkeyup "onkeyup", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondragend "ondragend",
|
||||||
onload "onload", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondragenter` attribute specifies the event handler for the dragenter event.
|
||||||
onloadeddata "onloadeddata", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondragenter "ondragenter",
|
||||||
onloadedmetadata "onloadedmetadata", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondragleave` attribute specifies the event handler for the dragleave event.
|
||||||
onloadstart "onloadstart", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondragleave "ondragleave",
|
||||||
onmousedown "onmousedown", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondragover` attribute specifies the event handler for the dragover event.
|
||||||
onmouseenter "onmouseenter", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondragover "ondragover",
|
||||||
onmouseleave "onmouseleave", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondragstart` attribute specifies the event handler for the dragstart event.
|
||||||
onmousemove "onmousemove", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondragstart "ondragstart",
|
||||||
onmouseout "onmouseout", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondrop` attribute specifies the event handler for the drop event.
|
||||||
onmouseover "onmouseover", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondrop "ondrop",
|
||||||
onmouseup "onmouseup", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `ondurationchange` attribute specifies the event handler for the durationchange event.
|
||||||
onmousewheel "onmousewheel", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
ondurationchange "ondurationchange",
|
||||||
onpause "onpause", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onemptied` attribute specifies the event handler for the emptied event.
|
||||||
onplay "onplay", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onemptied "onemptied",
|
||||||
onplaying "onplaying", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onended` attribute specifies the event handler for the ended event.
|
||||||
onprogress "onprogress", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onended "onended",
|
||||||
onratechange "onratechange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onerror` attribute specifies the event handler for the error event.
|
||||||
onreset "onreset", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onerror "onerror",
|
||||||
onresize "onresize", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onfocus` attribute specifies the event handler for the focus event.
|
||||||
onscroll "onscroll", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onfocus "onfocus",
|
||||||
onseeked "onseeked", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onformdata` attribute specifies the event handler for the formdata event.
|
||||||
onseeking "onseeking", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onformdata "onformdata",
|
||||||
onselect "onselect", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `oninput` attribute specifies the event handler for the input event.
|
||||||
onshow "onshow", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
oninput "oninput",
|
||||||
onsort "onsort", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `oninvalid` attribute specifies the event handler for the invalid event.
|
||||||
onstalled "onstalled", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
oninvalid "oninvalid",
|
||||||
onsubmit "onsubmit", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onkeydown` attribute specifies the event handler for the keydown event.
|
||||||
onsuspend "onsuspend", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onkeydown "onkeydown",
|
||||||
ontimeupdate "ontimeupdate", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onkeypress` attribute specifies the event handler for the keypress event.
|
||||||
ontoggle "ontoggle", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onkeypress "onkeypress",
|
||||||
onvolumechange "onvolumechange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
/// The `onkeyup` attribute specifies the event handler for the keyup event.
|
||||||
onwaiting "onwaiting", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
onkeyup "onkeyup",
|
||||||
|
/// The `onlanguagechange` attribute specifies the event handler for the languagechange event.
|
||||||
|
onlanguagechange "onlanguagechange",
|
||||||
|
/// The `onload` attribute specifies the event handler for the load event.
|
||||||
|
onload "onload",
|
||||||
|
/// The `onloadeddata` attribute specifies the event handler for the loadeddata event.
|
||||||
|
onloadeddata "onloadeddata",
|
||||||
|
/// The `onloadedmetadata` attribute specifies the event handler for the loadedmetadata event.
|
||||||
|
onloadedmetadata "onloadedmetadata",
|
||||||
|
/// The `onloadstart` attribute specifies the event handler for the loadstart event.
|
||||||
|
onloadstart "onloadstart",
|
||||||
|
/// The `onmousedown` attribute specifies the event handler for the mousedown event.
|
||||||
|
onmousedown "onmousedown",
|
||||||
|
/// The `onmouseenter` attribute specifies the event handler for the mouseenter event.
|
||||||
|
onmouseenter "onmouseenter",
|
||||||
|
/// The `onmouseleave` attribute specifies the event handler for the mouseleave event.
|
||||||
|
onmouseleave "onmouseleave",
|
||||||
|
/// The `onmousemove` attribute specifies the event handler for the mousemove event.
|
||||||
|
onmousemove "onmousemove",
|
||||||
|
/// The `onmouseout` attribute specifies the event handler for the mouseout event.
|
||||||
|
onmouseout "onmouseout",
|
||||||
|
/// The `onmouseover` attribute specifies the event handler for the mouseover event.
|
||||||
|
onmouseover "onmouseover",
|
||||||
|
/// The `onmouseup` attribute specifies the event handler for the mouseup event.
|
||||||
|
onmouseup "onmouseup",
|
||||||
|
/// The `onpause` attribute specifies the event handler for the pause event.
|
||||||
|
onpause "onpause",
|
||||||
|
/// The `onplay` attribute specifies the event handler for the play event.
|
||||||
|
onplay "onplay",
|
||||||
|
/// The `onplaying` attribute specifies the event handler for the playing event.
|
||||||
|
onplaying "onplaying",
|
||||||
|
/// The `onprogress` attribute specifies the event handler for the progress event.
|
||||||
|
onprogress "onprogress",
|
||||||
|
/// The `onratechange` attribute specifies the event handler for the ratechange event.
|
||||||
|
onratechange "onratechange",
|
||||||
|
/// The `onreset` attribute specifies the event handler for the reset event.
|
||||||
|
onreset "onreset",
|
||||||
|
/// The `onresize` attribute specifies the event handler for the resize event.
|
||||||
|
onresize "onresize",
|
||||||
|
/// The `onscroll` attribute specifies the event handler for the scroll event.
|
||||||
|
onscroll "onscroll",
|
||||||
|
/// The `onsecuritypolicyviolation` attribute specifies the event handler for the securitypolicyviolation event.
|
||||||
|
onsecuritypolicyviolation "onsecuritypolicyviolation",
|
||||||
|
/// The `onseeked` attribute specifies the event handler for the seeked event.
|
||||||
|
onseeked "onseeked",
|
||||||
|
/// The `onseeking` attribute specifies the event handler for the seeking event.
|
||||||
|
onseeking "onseeking",
|
||||||
|
/// The `onselect` attribute specifies the event handler for the select event.
|
||||||
|
onselect "onselect",
|
||||||
|
/// The `onslotchange` attribute specifies the event handler for the slotchange event.
|
||||||
|
onslotchange "onslotchange",
|
||||||
|
/// The `onstalled` attribute specifies the event handler for the stalled event.
|
||||||
|
onstalled "onstalled",
|
||||||
|
/// The `onsubmit` attribute specifies the event handler for the submit event.
|
||||||
|
onsubmit "onsubmit",
|
||||||
|
/// The `onsuspend` attribute specifies the event handler for the suspend event.
|
||||||
|
onsuspend "onsuspend",
|
||||||
|
/// The `ontimeupdate` attribute specifies the event handler for the timeupdate event.
|
||||||
|
ontimeupdate "ontimeupdate",
|
||||||
|
/// The `ontoggle` attribute specifies the event handler for the toggle event.
|
||||||
|
ontoggle "ontoggle",
|
||||||
|
/// The `onvolumechange` attribute specifies the event handler for the volumechange event.
|
||||||
|
onvolumechange "onvolumechange",
|
||||||
|
/// The `onwaiting` attribute specifies the event handler for the waiting event.
|
||||||
|
onwaiting "onwaiting",
|
||||||
|
/// The `onwebkitanimationend` attribute specifies the event handler for the webkitanimationend event.
|
||||||
|
onwebkitanimationend "onwebkitanimationend",
|
||||||
|
/// The `onwebkitanimationiteration` attribute specifies the event handler for the webkitanimationiteration event.
|
||||||
|
onwebkitanimationiteration "onwebkitanimationiteration",
|
||||||
|
/// The `onwebkitanimationstart` attribute specifies the event handler for the webkitanimationstart event.
|
||||||
|
onwebkitanimationstart "onwebkitanimationstart",
|
||||||
|
/// The `onwebkittransitionend` attribute specifies the event handler for the webkittransitionend event.
|
||||||
|
onwebkittransitionend "onwebkittransitionend",
|
||||||
|
/// The `onwheel` attribute specifies the event handler for the wheel event.
|
||||||
|
onwheel "onwheel",
|
||||||
|
|
||||||
// MathML attributes that aren't in HTML
|
// MathML attributes
|
||||||
|
/// The `accent` attribute specifies whether the element should be treated as an accent.
|
||||||
accent "accent",
|
accent "accent",
|
||||||
|
/// The `accentunder` attribute specifies whether the element should be treated as an accent under the base element.
|
||||||
accentunder "accentunder",
|
accentunder "accentunder",
|
||||||
|
/// The `columnalign` attribute specifies the alignment of columns.
|
||||||
columnalign "columnalign",
|
columnalign "columnalign",
|
||||||
|
/// The `columnlines` attribute specifies the presence of lines between columns.
|
||||||
columnlines "columnlines",
|
columnlines "columnlines",
|
||||||
|
/// The `columnspacing` attribute specifies the spacing between columns.
|
||||||
columnspacing "columnspacing",
|
columnspacing "columnspacing",
|
||||||
|
/// The `columnspan` attribute specifies the number of columns the element should span.
|
||||||
columnspan "columnspan",
|
columnspan "columnspan",
|
||||||
|
/// The `depth` attribute specifies the depth of the element.
|
||||||
depth "depth",
|
depth "depth",
|
||||||
|
/// The `display` attribute specifies the display style of the element.
|
||||||
display "display",
|
display "display",
|
||||||
|
/// The `displaystyle` attribute specifies whether the element is displayed in display style.
|
||||||
displaystyle "displaystyle",
|
displaystyle "displaystyle",
|
||||||
|
/// The `fence` attribute specifies whether the element should act as a fence.
|
||||||
fence "fence",
|
fence "fence",
|
||||||
|
/// The `frame` attribute specifies the type of frame for the element.
|
||||||
frame "frame",
|
frame "frame",
|
||||||
|
/// The `framespacing` attribute specifies the spacing around frames.
|
||||||
framespacing "framespacing",
|
framespacing "framespacing",
|
||||||
|
/// The `linethickness` attribute specifies the thickness of lines.
|
||||||
linethickness "linethickness",
|
linethickness "linethickness",
|
||||||
|
/// The `lspace` attribute specifies the space on the left side of the element.
|
||||||
lspace "lspace",
|
lspace "lspace",
|
||||||
|
/// The `mathbackground` attribute specifies the background color of the element.
|
||||||
mathbackground "mathbackground",
|
mathbackground "mathbackground",
|
||||||
|
/// The `mathcolor` attribute specifies the color of the element.
|
||||||
mathcolor "mathcolor",
|
mathcolor "mathcolor",
|
||||||
|
/// The `mathsize` attribute specifies the size of the element.
|
||||||
mathsize "mathsize",
|
mathsize "mathsize",
|
||||||
|
/// The `mathvariant` attribute specifies the mathematical variant of the element.
|
||||||
mathvariant "mathvariant",
|
mathvariant "mathvariant",
|
||||||
|
/// The `maxsize` attribute specifies the maximum size of the element.
|
||||||
maxsize "maxsize",
|
maxsize "maxsize",
|
||||||
|
/// The `minsize` attribute specifies the minimum size of the element.
|
||||||
minsize "minsize",
|
minsize "minsize",
|
||||||
|
/// The `movablelimits` attribute specifies whether the limits of the element are movable.
|
||||||
movablelimits "movablelimits",
|
movablelimits "movablelimits",
|
||||||
|
/// The `notation` attribute specifies the type of notation for the element.
|
||||||
notation "notation",
|
notation "notation",
|
||||||
|
/// The `rowalign` attribute specifies the alignment of rows.
|
||||||
rowalign "rowalign",
|
rowalign "rowalign",
|
||||||
|
/// The `rowlines` attribute specifies the presence of lines between rows.
|
||||||
rowlines "rowlines",
|
rowlines "rowlines",
|
||||||
|
/// The `rowspacing` attribute specifies the spacing between rows.
|
||||||
rowspacing "rowspacing",
|
rowspacing "rowspacing",
|
||||||
|
/// The `rspace` attribute specifies the space on the right side of the element.
|
||||||
rspace "rspace",
|
rspace "rspace",
|
||||||
|
/// The `scriptlevel` attribute specifies the script level of the element.
|
||||||
scriptlevel "scriptlevel",
|
scriptlevel "scriptlevel",
|
||||||
|
/// The `separator` attribute specifies whether the element is a separator.
|
||||||
separator "separator",
|
separator "separator",
|
||||||
|
/// The `stretchy` attribute specifies whether the element is stretchy.
|
||||||
stretchy "stretchy",
|
stretchy "stretchy",
|
||||||
|
/// The `symmetric` attribute specifies whether the element is symmetric.
|
||||||
symmetric "symmetric",
|
symmetric "symmetric",
|
||||||
|
/// The `voffset` attribute specifies the vertical offset of the element.
|
||||||
voffset "voffset",
|
voffset "voffset",
|
||||||
|
/// The `xmlns` attribute specifies the XML namespace of the element.
|
||||||
xmlns "xmlns",
|
xmlns "xmlns",
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
/// A type-erased `AnyAttribute`.
|
||||||
pub mod any_attribute;
|
pub mod any_attribute;
|
||||||
|
/// Types for ARIA attributes.
|
||||||
pub mod aria;
|
pub mod aria;
|
||||||
|
/// Types for custom attributes.
|
||||||
pub mod custom;
|
pub mod custom;
|
||||||
|
/// Traits to define global attribute methods on all HTML elements.
|
||||||
pub mod global;
|
pub mod global;
|
||||||
mod key;
|
mod key;
|
||||||
mod value;
|
mod value;
|
||||||
|
@ -12,16 +16,29 @@ pub use key::*;
|
||||||
use std::{fmt::Debug, future::Future, marker::PhantomData};
|
use std::{fmt::Debug, future::Future, marker::PhantomData};
|
||||||
pub use value::*;
|
pub use value::*;
|
||||||
|
|
||||||
|
/// Defines an attribute: anything that can modify an element.
|
||||||
pub trait Attribute<R: Renderer>: NextAttribute<R> + Send {
|
pub trait Attribute<R: Renderer>: NextAttribute<R> + Send {
|
||||||
|
/// The minimum length of this attribute in HTML.
|
||||||
const MIN_LENGTH: usize;
|
const MIN_LENGTH: usize;
|
||||||
|
|
||||||
|
/// The state that should be retained between building and rebuilding.
|
||||||
type State;
|
type State;
|
||||||
|
/// The type once all async data have loaded.
|
||||||
type AsyncOutput: Attribute<R>;
|
type AsyncOutput: Attribute<R>;
|
||||||
|
/// An equivalent to this attribute that can be cloned to be shared across elements.
|
||||||
type Cloneable: Attribute<R> + Clone;
|
type Cloneable: Attribute<R> + Clone;
|
||||||
|
/// An equivalent to this attribute that can be cloned to be shared across elements, and
|
||||||
|
/// captures no references shorter than `'static`.
|
||||||
type CloneableOwned: Attribute<R> + Clone + 'static;
|
type CloneableOwned: Attribute<R> + Clone + 'static;
|
||||||
|
|
||||||
|
/// An approximation of the actual length of this attribute in HTML.
|
||||||
fn html_len(&self) -> usize;
|
fn html_len(&self) -> usize;
|
||||||
|
|
||||||
|
/// Renders the attribute to HTML.
|
||||||
|
///
|
||||||
|
/// This separates a general buffer for attribute values from the `class` and `style`
|
||||||
|
/// attributes, so that multiple classes or styles can be combined, and also allows for an
|
||||||
|
/// `inner_html` attribute that sets the child HTML instead of an attribute.
|
||||||
fn to_html(
|
fn to_html(
|
||||||
self,
|
self,
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
|
@ -30,24 +47,39 @@ pub trait Attribute<R: Renderer>: NextAttribute<R> + Send {
|
||||||
inner_html: &mut String,
|
inner_html: &mut String,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Adds interactivity as necessary, given DOM nodes that were created from HTML that has
|
||||||
|
/// either been rendered on the server, or cloned for a `<template>`.
|
||||||
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Adds this attribute to the element during client-side rendering.
|
||||||
fn build(self, el: &R::Element) -> Self::State;
|
fn build(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Applies a new value for the attribute.
|
||||||
fn rebuild(self, state: &mut Self::State);
|
fn rebuild(self, state: &mut Self::State);
|
||||||
|
|
||||||
|
/// Converts this attribute into an equivalent that can be cloned.
|
||||||
fn into_cloneable(self) -> Self::Cloneable;
|
fn into_cloneable(self) -> Self::Cloneable;
|
||||||
|
|
||||||
|
/// Converts this attributes into an equivalent that can be cloned and is `'static`.
|
||||||
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
||||||
|
|
||||||
|
/// “Runs” the attribute without other side effects. For primitive types, this is a no-op. For
|
||||||
|
/// reactive types, this can be used to gather data about reactivity or about asynchronous data
|
||||||
|
/// that needs to be loaded.
|
||||||
fn dry_resolve(&mut self);
|
fn dry_resolve(&mut self);
|
||||||
|
|
||||||
|
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds another attribute to this one, returning a new attribute.
|
||||||
|
///
|
||||||
|
/// This is typically achieved by creating or extending a tuple of attributes.
|
||||||
pub trait NextAttribute<R: Renderer> {
|
pub trait NextAttribute<R: Renderer> {
|
||||||
|
/// The type of the new, combined attribute.
|
||||||
type Output<NewAttr: Attribute<R>>: Attribute<R>;
|
type Output<NewAttr: Attribute<R>>: Attribute<R>;
|
||||||
|
|
||||||
|
/// Adds a new attribute.
|
||||||
fn add_any_attr<NewAttr: Attribute<R>>(
|
fn add_any_attr<NewAttr: Attribute<R>>(
|
||||||
self,
|
self,
|
||||||
new_attr: NewAttr,
|
new_attr: NewAttr,
|
||||||
|
@ -112,6 +144,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An attribute with a key and value.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Attr<K, V, R>(pub K, pub V, pub PhantomData<R>)
|
pub struct Attr<K, V, R>(pub K, pub V, pub PhantomData<R>)
|
||||||
where
|
where
|
||||||
|
|
|
@ -11,8 +11,12 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A possible value for an HTML attribute.
|
||||||
pub trait AttributeValue<R: Renderer>: Send {
|
pub trait AttributeValue<R: Renderer>: Send {
|
||||||
|
/// The state that should be retained between building and rebuilding.
|
||||||
type State;
|
type State;
|
||||||
|
|
||||||
|
/// The type once all async data have loaded.
|
||||||
type AsyncOutput: AttributeValue<R>;
|
type AsyncOutput: AttributeValue<R>;
|
||||||
|
|
||||||
/// A version of the value that can be cloned. This can be the same type, or a
|
/// A version of the value that can be cloned. This can be the same type, or a
|
||||||
|
@ -28,28 +32,41 @@ pub trait AttributeValue<R: Renderer>: Send {
|
||||||
/// cloneable type has worse performance than the cloneable type, so they are separate.
|
/// cloneable type has worse performance than the cloneable type, so they are separate.
|
||||||
type CloneableOwned: AttributeValue<R> + Clone + 'static;
|
type CloneableOwned: AttributeValue<R> + Clone + 'static;
|
||||||
|
|
||||||
|
/// An approximation of the actual length of this attribute in HTML.
|
||||||
fn html_len(&self) -> usize;
|
fn html_len(&self) -> usize;
|
||||||
|
|
||||||
|
/// Renders the attribute value to HTML.
|
||||||
fn to_html(self, key: &str, buf: &mut String);
|
fn to_html(self, key: &str, buf: &mut String);
|
||||||
|
|
||||||
|
/// Renders the attribute value to HTML for a `<template>`.
|
||||||
fn to_template(key: &str, buf: &mut String);
|
fn to_template(key: &str, buf: &mut String);
|
||||||
|
|
||||||
|
/// Adds interactivity as necessary, given DOM nodes that were created from HTML that has
|
||||||
|
/// either been rendered on the server, or cloned for a `<template>`.
|
||||||
fn hydrate<const FROM_SERVER: bool>(
|
fn hydrate<const FROM_SERVER: bool>(
|
||||||
self,
|
self,
|
||||||
key: &str,
|
key: &str,
|
||||||
el: &R::Element,
|
el: &R::Element,
|
||||||
) -> Self::State;
|
) -> Self::State;
|
||||||
|
|
||||||
|
/// Adds this attribute to the element during client-side rendering.
|
||||||
fn build(self, el: &R::Element, key: &str) -> Self::State;
|
fn build(self, el: &R::Element, key: &str) -> Self::State;
|
||||||
|
|
||||||
|
/// Applies a new value for the attribute.
|
||||||
fn rebuild(self, key: &str, state: &mut Self::State);
|
fn rebuild(self, key: &str, state: &mut Self::State);
|
||||||
|
|
||||||
|
/// Converts this attribute into an equivalent that can be cloned.
|
||||||
fn into_cloneable(self) -> Self::Cloneable;
|
fn into_cloneable(self) -> Self::Cloneable;
|
||||||
|
|
||||||
|
/// Converts this attributes into an equivalent that can be cloned and is `'static`.
|
||||||
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
||||||
|
|
||||||
|
/// “Runs” the attribute without other side effects. For primitive types, this is a no-op. For
|
||||||
|
/// reactive types, this can be used to gather data about reactivity or about asynchronous data
|
||||||
|
/// that needs to be loaded.
|
||||||
fn dry_resolve(&mut self);
|
fn dry_resolve(&mut self);
|
||||||
|
|
||||||
|
/// “Resolves” this into a form that is not waiting for any asynchronous data.
|
||||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::{future::Future, marker::PhantomData, sync::Arc};
|
use std::{future::Future, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
|
/// Adds a CSS class.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn class<C, R>(class: C) -> Class<C, R>
|
pub fn class<C, R>(class: C) -> Class<C, R>
|
||||||
where
|
where
|
||||||
|
@ -17,6 +18,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A CSS class.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Class<C, R> {
|
pub struct Class<C, R> {
|
||||||
class: C,
|
class: C,
|
||||||
|
@ -133,34 +135,54 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A possible value for a CSS class.
|
||||||
pub trait IntoClass<R: DomRenderer>: Send {
|
pub trait IntoClass<R: DomRenderer>: Send {
|
||||||
|
/// The HTML that should be included in a `<template>`.
|
||||||
const TEMPLATE: &'static str = "";
|
const TEMPLATE: &'static str = "";
|
||||||
|
/// The minimum length of the HTML.
|
||||||
const MIN_LENGTH: usize = Self::TEMPLATE.len();
|
const MIN_LENGTH: usize = Self::TEMPLATE.len();
|
||||||
|
|
||||||
|
/// The type after all async data have resolved.
|
||||||
type AsyncOutput: IntoClass<R>;
|
type AsyncOutput: IntoClass<R>;
|
||||||
|
/// The view state retained between building and rebuilding.
|
||||||
type State;
|
type State;
|
||||||
|
/// An equivalent value that can be cloned.
|
||||||
type Cloneable: IntoClass<R> + Clone;
|
type Cloneable: IntoClass<R> + Clone;
|
||||||
|
/// An equivalent value that can be cloned and is `'static`.
|
||||||
type CloneableOwned: IntoClass<R> + Clone + 'static;
|
type CloneableOwned: IntoClass<R> + Clone + 'static;
|
||||||
|
|
||||||
|
/// The estimated length of the HTML.
|
||||||
fn html_len(&self) -> usize;
|
fn html_len(&self) -> usize;
|
||||||
|
|
||||||
|
/// Renders the class to HTML.
|
||||||
fn to_html(self, class: &mut String);
|
fn to_html(self, class: &mut String);
|
||||||
|
|
||||||
|
/// Renders the class to HTML for a `<template>`.
|
||||||
#[allow(unused)] // it's used with `nightly` feature
|
#[allow(unused)] // it's used with `nightly` feature
|
||||||
fn to_template(class: &mut String) {}
|
fn to_template(class: &mut String) {}
|
||||||
|
|
||||||
|
/// Adds interactivity as necessary, given DOM nodes that were created from HTML that has
|
||||||
|
/// either been rendered on the server, or cloned for a `<template>`.
|
||||||
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Adds this class to the element during client-side rendering.
|
||||||
fn build(self, el: &R::Element) -> Self::State;
|
fn build(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Updates the value.
|
||||||
fn rebuild(self, state: &mut Self::State);
|
fn rebuild(self, state: &mut Self::State);
|
||||||
|
|
||||||
|
/// Converts this to a cloneable type.
|
||||||
fn into_cloneable(self) -> Self::Cloneable;
|
fn into_cloneable(self) -> Self::Cloneable;
|
||||||
|
|
||||||
|
/// Converts this to a cloneable, owned type.
|
||||||
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
||||||
|
|
||||||
|
/// “Runs” the attribute without other side effects. For primitive types, this is a no-op. For
|
||||||
|
/// reactive types, this can be used to gather data about reactivity or about asynchronous data
|
||||||
|
/// that needs to be loaded.
|
||||||
fn dry_resolve(&mut self);
|
fn dry_resolve(&mut self);
|
||||||
|
|
||||||
|
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,18 @@ use crate::{
|
||||||
use send_wrapper::SendWrapper;
|
use send_wrapper::SendWrapper;
|
||||||
use std::{marker::PhantomData, sync::Arc};
|
use std::{marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
|
/// Adds a directive to the element, which runs some custom logic in the browser when the element
|
||||||
|
/// is created or hydrated.
|
||||||
pub trait DirectiveAttribute<T, P, D, Rndr>
|
pub trait DirectiveAttribute<T, P, D, Rndr>
|
||||||
where
|
where
|
||||||
D: IntoDirective<T, P, Rndr>,
|
D: IntoDirective<T, P, Rndr>,
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
|
/// The type of the element with the directive added.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Adds a directive to the element, which runs some custom logic in the browser when the element
|
||||||
|
/// is created or hydrated.
|
||||||
fn directive(self, handler: D, param: P) -> Self::Output;
|
fn directive(self, handler: D, param: P) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +37,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a directive to the element, which runs some custom logic in the browser when the element
|
||||||
|
/// is created or hydrated.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn directive<T, P, D, R>(handler: D, param: P) -> Directive<T, D, P, R>
|
pub fn directive<T, P, D, R>(handler: D, param: P) -> Directive<T, D, P, R>
|
||||||
where
|
where
|
||||||
|
@ -46,6 +53,7 @@ where
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Custom logic that runs in the browser when the element is created or hydrated.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Directive<T, D, P, R>(SendWrapper<DirectiveInner<T, D, P, R>>);
|
pub struct Directive<T, D, P, R>(SendWrapper<DirectiveInner<T, D, P, R>>);
|
||||||
|
|
||||||
|
@ -60,7 +68,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DirectiveInner<T, D, P, R> {
|
struct DirectiveInner<T, D, P, R> {
|
||||||
handler: D,
|
handler: D,
|
||||||
param: P,
|
param: P,
|
||||||
t: PhantomData<T>,
|
t: PhantomData<T>,
|
||||||
|
@ -229,11 +237,13 @@ impl<T, D, P, R> ToTemplate for Directive<T, D, P, R> {
|
||||||
/// The first is the element the directive is added to and the optional
|
/// The first is the element the directive is added to and the optional
|
||||||
/// second is the parameter that is provided in the attribute.
|
/// second is the parameter that is provided in the attribute.
|
||||||
pub trait IntoDirective<T: ?Sized, P, R: Renderer> {
|
pub trait IntoDirective<T: ?Sized, P, R: Renderer> {
|
||||||
|
/// An equivalent to this directive that is cloneable and owned.
|
||||||
type Cloneable: IntoDirective<T, P, R> + Clone + 'static;
|
type Cloneable: IntoDirective<T, P, R> + Clone + 'static;
|
||||||
|
|
||||||
/// Calls the handler function
|
/// Calls the handler function
|
||||||
fn run(&self, el: R::Element, param: P);
|
fn run(&self, el: R::Element, param: P);
|
||||||
|
|
||||||
|
/// Converts this into a cloneable type.
|
||||||
fn into_cloneable(self) -> Self::Cloneable;
|
fn into_cloneable(self) -> Self::Cloneable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
use std::{borrow::Cow, fmt::Debug, marker::PhantomData, sync::Arc};
|
use std::{borrow::Cow, fmt::Debug, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
// FIXME custom element HTML rendering is broken because tag names aren't static
|
// FIXME custom element HTML rendering is broken because tag names aren't static
|
||||||
|
/// Creates a custom element.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn custom<E, Rndr>(tag: E) -> HtmlElement<Custom<E>, (), (), Rndr>
|
pub fn custom<E, Rndr>(tag: E) -> HtmlElement<Custom<E>, (), (), Rndr>
|
||||||
where
|
where
|
||||||
|
@ -22,6 +23,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A custom HTML element.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct Custom<E>(E)
|
pub struct Custom<E>(E)
|
||||||
where
|
where
|
||||||
|
@ -57,8 +59,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The element name for a custom element.
|
||||||
// TODO these are all broken for custom elements
|
// TODO these are all broken for custom elements
|
||||||
pub trait CustomElementKey: AsRef<str> + Send {
|
pub trait CustomElementKey: AsRef<str> + Send {
|
||||||
|
/// The element name.
|
||||||
const KEY: &'static str;
|
const KEY: &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,18 +27,22 @@ use web_sys::Element;
|
||||||
/// let remove = element.on(ev::blur, move |_| /* ... */);
|
/// let remove = element.on(ev::blur, move |_| /* ... */);
|
||||||
/// ```
|
/// ```
|
||||||
pub trait ElementExt {
|
pub trait ElementExt {
|
||||||
|
/// Adds an attribute to the element, at runtime.
|
||||||
fn attr<At>(&self, attribute: At) -> At::State
|
fn attr<At>(&self, attribute: At) -> At::State
|
||||||
where
|
where
|
||||||
At: Attribute<Dom>;
|
At: Attribute<Dom>;
|
||||||
|
|
||||||
|
/// Adds a class to the element, at runtime.
|
||||||
fn class<C>(&self, class: C) -> C::State
|
fn class<C>(&self, class: C) -> C::State
|
||||||
where
|
where
|
||||||
C: IntoClass<Dom>;
|
C: IntoClass<Dom>;
|
||||||
|
|
||||||
|
/// Adds a style to the element, at runtime.
|
||||||
fn style<S>(&self, style: S) -> S::State
|
fn style<S>(&self, style: S) -> S::State
|
||||||
where
|
where
|
||||||
S: IntoStyle<Dom>;
|
S: IntoStyle<Dom>;
|
||||||
|
|
||||||
|
/// Adds an event listener to the element, at runtime.
|
||||||
fn on<E>(
|
fn on<E>(
|
||||||
&self,
|
&self,
|
||||||
ev: E,
|
ev: E,
|
||||||
|
|
|
@ -6,6 +6,14 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::{future::Future, marker::PhantomData, sync::Arc};
|
use std::{future::Future, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
|
/// Returns an [`Attribute`] that sets the inner HTML of an element.
|
||||||
|
///
|
||||||
|
/// No children should be given to this element, as this HTML will be used instead.
|
||||||
|
///
|
||||||
|
/// # Security
|
||||||
|
/// Be very careful when using this method. Always remember to
|
||||||
|
/// sanitize the input to avoid a cross-site scripting (XSS)
|
||||||
|
/// vulnerability.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn inner_html<T, R>(value: T) -> InnerHtml<T, R>
|
pub fn inner_html<T, R>(value: T) -> InnerHtml<T, R>
|
||||||
where
|
where
|
||||||
|
@ -18,6 +26,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the inner HTML of an element.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InnerHtml<T, R> {
|
pub struct InnerHtml<T, R> {
|
||||||
value: T,
|
value: T,
|
||||||
|
@ -118,12 +127,21 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the inner HTML of an element.
|
||||||
pub trait InnerHtmlAttribute<T, Rndr>
|
pub trait InnerHtmlAttribute<T, Rndr>
|
||||||
where
|
where
|
||||||
T: InnerHtmlValue<Rndr>,
|
T: InnerHtmlValue<Rndr>,
|
||||||
Rndr: DomRenderer,
|
Rndr: DomRenderer,
|
||||||
Self: Sized + AddAnyAttr<Rndr>,
|
Self: Sized + AddAnyAttr<Rndr>,
|
||||||
{
|
{
|
||||||
|
/// Sets the inner HTML of this element.
|
||||||
|
///
|
||||||
|
/// No children should be given to this element, as this HTML will be used instead.
|
||||||
|
///
|
||||||
|
/// # Security
|
||||||
|
/// Be very careful when using this method. Always remember to
|
||||||
|
/// sanitize the input to avoid a cross-site scripting (XSS)
|
||||||
|
/// vulnerability.
|
||||||
fn inner_html(
|
fn inner_html(
|
||||||
self,
|
self,
|
||||||
value: T,
|
value: T,
|
||||||
|
@ -149,30 +167,48 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A possible value for [`InnerHtml`].
|
||||||
pub trait InnerHtmlValue<R: DomRenderer>: Send {
|
pub trait InnerHtmlValue<R: DomRenderer>: Send {
|
||||||
|
/// The type after all async data have resolved.
|
||||||
type AsyncOutput: InnerHtmlValue<R>;
|
type AsyncOutput: InnerHtmlValue<R>;
|
||||||
|
/// The view state retained between building and rebuilding.
|
||||||
type State;
|
type State;
|
||||||
|
/// An equivalent value that can be cloned.
|
||||||
type Cloneable: InnerHtmlValue<R> + Clone;
|
type Cloneable: InnerHtmlValue<R> + Clone;
|
||||||
|
/// An equivalent value that can be cloned and is `'static`.
|
||||||
type CloneableOwned: InnerHtmlValue<R> + Clone + 'static;
|
type CloneableOwned: InnerHtmlValue<R> + Clone + 'static;
|
||||||
|
|
||||||
|
/// The estimated length of the HTML.
|
||||||
fn html_len(&self) -> usize;
|
fn html_len(&self) -> usize;
|
||||||
|
|
||||||
|
/// Renders the class to HTML.
|
||||||
fn to_html(self, buf: &mut String);
|
fn to_html(self, buf: &mut String);
|
||||||
|
|
||||||
|
/// Renders the class to HTML for a `<template>`.
|
||||||
fn to_template(buf: &mut String);
|
fn to_template(buf: &mut String);
|
||||||
|
|
||||||
|
/// Adds interactivity as necessary, given DOM nodes that were created from HTML that has
|
||||||
|
/// either been rendered on the server, or cloned for a `<template>`.
|
||||||
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Adds this class to the element during client-side rendering.
|
||||||
fn build(self, el: &R::Element) -> Self::State;
|
fn build(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Updates the value.
|
||||||
fn rebuild(self, state: &mut Self::State);
|
fn rebuild(self, state: &mut Self::State);
|
||||||
|
|
||||||
|
/// Converts this to a cloneable type.
|
||||||
fn into_cloneable(self) -> Self::Cloneable;
|
fn into_cloneable(self) -> Self::Cloneable;
|
||||||
|
|
||||||
|
/// Converts this to a cloneable, owned type.
|
||||||
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
||||||
|
|
||||||
|
/// “Runs” the attribute without other side effects. For primitive types, this is a no-op. For
|
||||||
|
/// reactive types, this can be used to gather data about reactivity or about asynchronous data
|
||||||
|
/// that needs to be loaded.
|
||||||
fn dry_resolve(&mut self);
|
fn dry_resolve(&mut self);
|
||||||
|
|
||||||
|
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub use element_ext::*;
|
||||||
pub use elements::*;
|
pub use elements::*;
|
||||||
pub use inner_html::*;
|
pub use inner_html::*;
|
||||||
|
|
||||||
|
/// The typed representation of an HTML element.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct HtmlElement<E, At, Ch, Rndr> {
|
pub struct HtmlElement<E, At, Ch, Rndr> {
|
||||||
pub(crate) tag: E,
|
pub(crate) tag: E,
|
||||||
|
@ -50,24 +51,6 @@ where
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
impl<E, At, Ch, Rndr> HtmlElement<E, At, Ch, Rndr> {
|
|
||||||
pub fn children(&self) -> &Ch {
|
|
||||||
&self.children
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn children_mut(&mut self) -> &mut Ch {
|
|
||||||
&mut self.children
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn attributes(&self) -> &At {
|
|
||||||
&self.attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn attributes_mut(&mut self) -> &mut At {
|
|
||||||
&mut self.attributes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E, At, Ch, NewChild, Rndr> ElementChild<Rndr, NewChild>
|
impl<E, At, Ch, NewChild, Rndr> ElementChild<Rndr, NewChild>
|
||||||
for HtmlElement<E, At, Ch, Rndr>
|
for HtmlElement<E, At, Ch, Rndr>
|
||||||
where
|
where
|
||||||
|
@ -136,34 +119,48 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a child to the element.
|
||||||
pub trait ElementChild<Rndr, NewChild>
|
pub trait ElementChild<Rndr, NewChild>
|
||||||
where
|
where
|
||||||
NewChild: Render<Rndr>,
|
NewChild: Render<Rndr>,
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
|
/// The type of the element, with the child added.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Adds a child to an element.
|
||||||
fn child(self, child: NewChild) -> Self::Output;
|
fn child(self, child: NewChild) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An HTML element.
|
||||||
pub trait ElementType: Send {
|
pub trait ElementType: Send {
|
||||||
/// The underlying native widget type that this represents.
|
/// The underlying native widget type that this represents.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// The element's tag.
|
||||||
const TAG: &'static str;
|
const TAG: &'static str;
|
||||||
|
/// Whether the element is self-closing.
|
||||||
const SELF_CLOSING: bool;
|
const SELF_CLOSING: bool;
|
||||||
|
/// Whether the element's children should be escaped. This should be `true` except for elements
|
||||||
|
/// like `<style>` and `<script>`, which include other languages that should not use HTML
|
||||||
|
/// entity escaping.
|
||||||
const ESCAPE_CHILDREN: bool;
|
const ESCAPE_CHILDREN: bool;
|
||||||
|
|
||||||
|
/// The element's tag.
|
||||||
fn tag(&self) -> &str;
|
fn tag(&self) -> &str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Denotes that the type that implements this has a particular HTML element type.
|
||||||
pub trait HasElementType {
|
pub trait HasElementType {
|
||||||
|
/// The element type.
|
||||||
type ElementType;
|
type ElementType;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ElementWithChildren {}
|
pub(crate) trait ElementWithChildren {}
|
||||||
|
|
||||||
|
/// Creates an element.
|
||||||
pub trait CreateElement<R: Renderer> {
|
pub trait CreateElement<R: Renderer> {
|
||||||
|
/// Creates an element.
|
||||||
fn create_element(&self) -> R::Element;
|
fn create_element(&self) -> R::Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +383,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Renders an [`Attribute`] (which can be one or more HTML attributes) into an HTML buffer.
|
||||||
pub fn attributes_to_html<At, R>(attr: At, buf: &mut String) -> String
|
pub fn attributes_to_html<At, R>(attr: At, buf: &mut String) -> String
|
||||||
where
|
where
|
||||||
At: Attribute<R>,
|
At: Attribute<R>,
|
||||||
|
@ -423,10 +421,11 @@ where
|
||||||
inner_html
|
inner_html
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The retained view state for an HTML element.
|
||||||
pub struct ElementState<At, Ch, R: Renderer> {
|
pub struct ElementState<At, Ch, R: Renderer> {
|
||||||
pub el: R::Element,
|
pub(crate) el: R::Element,
|
||||||
pub attrs: At,
|
pub(crate) attrs: At,
|
||||||
pub children: Option<Ch>,
|
pub(crate) children: Option<Ch>,
|
||||||
rndr: PhantomData<R>,
|
rndr: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,15 @@ use std::{
|
||||||
};
|
};
|
||||||
use wasm_bindgen::convert::FromWasmAbi;
|
use wasm_bindgen::convert::FromWasmAbi;
|
||||||
|
|
||||||
|
/// A cloneable event callback.
|
||||||
pub type SharedEventCallback<E> = Rc<RefCell<dyn FnMut(E)>>;
|
pub type SharedEventCallback<E> = Rc<RefCell<dyn FnMut(E)>>;
|
||||||
|
|
||||||
|
/// A function that can be called in response to an event.
|
||||||
pub trait EventCallback<E>: 'static {
|
pub trait EventCallback<E>: 'static {
|
||||||
|
/// Runs the event handler.
|
||||||
fn invoke(&mut self, event: E);
|
fn invoke(&mut self, event: E);
|
||||||
|
|
||||||
|
/// Converts this into a cloneable/shared event handler.
|
||||||
fn into_shared(self) -> SharedEventCallback<E>;
|
fn into_shared(self) -> SharedEventCallback<E>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +50,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An event listener with a typed event target.
|
||||||
pub struct Targeted<E, T, R> {
|
pub struct Targeted<E, T, R> {
|
||||||
event: E,
|
event: E,
|
||||||
el_ty: PhantomData<T>,
|
el_ty: PhantomData<T>,
|
||||||
|
@ -53,10 +58,12 @@ pub struct Targeted<E, T, R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, T, R> Targeted<E, T, R> {
|
impl<E, T, R> Targeted<E, T, R> {
|
||||||
|
/// Returns the inner event.
|
||||||
pub fn into_inner(self) -> E {
|
pub fn into_inner(self) -> E {
|
||||||
self.event
|
self.event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the event's target, as an HTML element of the correct type.
|
||||||
pub fn target(&self) -> T
|
pub fn target(&self) -> T
|
||||||
where
|
where
|
||||||
T: CastFrom<R::Element>,
|
T: CastFrom<R::Element>,
|
||||||
|
@ -93,6 +100,7 @@ impl<E, T, R> From<E> for Targeted<E, T, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an [`Attribute`] that will add an event listener to an element.
|
||||||
pub fn on<E, F, R>(event: E, cb: F) -> On<E, F, R>
|
pub fn on<E, F, R>(event: E, cb: F) -> On<E, F, R>
|
||||||
where
|
where
|
||||||
F: FnMut(E::EventType) + 'static,
|
F: FnMut(E::EventType) + 'static,
|
||||||
|
@ -108,6 +116,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an [`Attribute`] that will add an event listener with a typed target to an element.
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn on_target<E, T, R, F>(
|
pub fn on_target<E, T, R, F>(
|
||||||
event: E,
|
event: E,
|
||||||
|
@ -125,6 +134,7 @@ where
|
||||||
on(event, Box::new(move |ev: E::EventType| cb(ev.into())))
|
on(event, Box::new(move |ev: E::EventType| cb(ev.into())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An [`Attribute`] that adds an event listener to an element.
|
||||||
pub struct On<E, F, R> {
|
pub struct On<E, F, R> {
|
||||||
event: E,
|
event: E,
|
||||||
cb: SendWrapper<F>,
|
cb: SendWrapper<F>,
|
||||||
|
@ -153,6 +163,7 @@ where
|
||||||
R: DomRenderer,
|
R: DomRenderer,
|
||||||
E::EventType: From<R::Event>,
|
E::EventType: From<R::Event>,
|
||||||
{
|
{
|
||||||
|
/// Attaches the event listener to the element.
|
||||||
pub fn attach(self, el: &R::Element) -> RemoveEventHandler<R::Element> {
|
pub fn attach(self, el: &R::Element) -> RemoveEventHandler<R::Element> {
|
||||||
fn attach_inner<R: DomRenderer>(
|
fn attach_inner<R: DomRenderer>(
|
||||||
el: &R::Element,
|
el: &R::Element,
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
// TODO serialized props, too
|
// TODO serialized props, too
|
||||||
|
/// An island of interactivity in an otherwise-inert HTML document.
|
||||||
pub struct Island<Rndr, View> {
|
pub struct Island<Rndr, View> {
|
||||||
component: &'static str,
|
component: &'static str,
|
||||||
view: View,
|
view: View,
|
||||||
|
@ -18,6 +19,7 @@ const ISLAND_TAG: &str = "leptos-island";
|
||||||
const ISLAND_CHILDREN_TAG: &str = "leptos-children";
|
const ISLAND_CHILDREN_TAG: &str = "leptos-children";
|
||||||
|
|
||||||
impl<Rndr, View> Island<Rndr, View> {
|
impl<Rndr, View> Island<Rndr, View> {
|
||||||
|
/// Creates a new island with the given component name.
|
||||||
pub fn new(component: &'static str, view: View) -> Self {
|
pub fn new(component: &'static str, view: View) -> Self {
|
||||||
Island {
|
Island {
|
||||||
component,
|
component,
|
||||||
|
@ -152,12 +154,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The children that will be projected into an [`Island`].
|
||||||
pub struct IslandChildren<Rndr, View> {
|
pub struct IslandChildren<Rndr, View> {
|
||||||
view: View,
|
view: View,
|
||||||
rndr: PhantomData<Rndr>,
|
rndr: PhantomData<Rndr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Rndr, View> IslandChildren<Rndr, View> {
|
impl<Rndr, View> IslandChildren<Rndr, View> {
|
||||||
|
/// Creates a new representation of the children.
|
||||||
pub fn new(view: View) -> Self {
|
pub fn new(view: View) -> Self {
|
||||||
IslandChildren {
|
IslandChildren {
|
||||||
view,
|
view,
|
||||||
|
|
|
@ -5,21 +5,32 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// Types for HTML attributes.
|
||||||
pub mod attribute;
|
pub mod attribute;
|
||||||
|
/// Types for manipulating the `class` attribute and `classList`.
|
||||||
pub mod class;
|
pub mod class;
|
||||||
|
/// Types for creating user-defined attributes with custom behavior (directives).
|
||||||
pub mod directive;
|
pub mod directive;
|
||||||
|
/// Types for HTML elements.
|
||||||
pub mod element;
|
pub mod element;
|
||||||
|
/// Types for DOM events.
|
||||||
pub mod event;
|
pub mod event;
|
||||||
|
/// Types for adding interactive islands to inert HTML pages.
|
||||||
pub mod islands;
|
pub mod islands;
|
||||||
|
/// Types for accessing a reference to an HTML element.
|
||||||
pub mod node_ref;
|
pub mod node_ref;
|
||||||
|
/// Types for DOM properties.
|
||||||
pub mod property;
|
pub mod property;
|
||||||
|
/// Types for the `style` attribute and individual style manipulation.
|
||||||
pub mod style;
|
pub mod style;
|
||||||
|
|
||||||
|
/// A `<!DOCTYPE>` declaration.
|
||||||
pub struct Doctype<R: Renderer> {
|
pub struct Doctype<R: Renderer> {
|
||||||
value: &'static str,
|
value: &'static str,
|
||||||
rndr: PhantomData<R>,
|
rndr: PhantomData<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a `<!DOCTYPE>`.
|
||||||
pub fn doctype<R: Renderer>(value: &'static str) -> Doctype<R> {
|
pub fn doctype<R: Renderer>(value: &'static str) -> Doctype<R> {
|
||||||
Doctype {
|
Doctype {
|
||||||
value,
|
value,
|
||||||
|
|
|
@ -8,14 +8,17 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// Describes a container that can be used to hold a reference to an HTML element.
|
||||||
pub trait NodeRefContainer<E, Rndr>: Send + Clone
|
pub trait NodeRefContainer<E, Rndr>: Send + Clone
|
||||||
where
|
where
|
||||||
E: ElementType,
|
E: ElementType,
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
|
/// Fills the container with the element.
|
||||||
fn load(self, el: &Rndr::Element);
|
fn load(self, el: &Rndr::Element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An [`Attribute`] that will fill a [`NodeRefContainer`] with an HTML element.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NodeRefAttr<E, C, Rndr> {
|
pub struct NodeRefAttr<E, C, Rndr> {
|
||||||
container: C,
|
container: C,
|
||||||
|
@ -36,6 +39,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an attribute that will fill a [`NodeRefContainer`] with the element it is applied to.
|
||||||
pub fn node_ref<E, C, Rndr>(container: C) -> NodeRefAttr<E, C, Rndr>
|
pub fn node_ref<E, C, Rndr>(container: C) -> NodeRefAttr<E, C, Rndr>
|
||||||
where
|
where
|
||||||
E: ElementType,
|
E: ElementType,
|
||||||
|
@ -125,6 +129,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds the `node_ref` attribute to an element.
|
||||||
pub trait NodeRefAttribute<E, C, Rndr>
|
pub trait NodeRefAttribute<E, C, Rndr>
|
||||||
where
|
where
|
||||||
E: ElementType,
|
E: ElementType,
|
||||||
|
@ -132,6 +137,7 @@ where
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
Rndr::Element: PartialEq,
|
Rndr::Element: PartialEq,
|
||||||
{
|
{
|
||||||
|
/// Binds this HTML element to a [`NodeRefContainer`].
|
||||||
fn node_ref(
|
fn node_ref(
|
||||||
self,
|
self,
|
||||||
container: C,
|
container: C,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use send_wrapper::SendWrapper;
|
||||||
use std::{borrow::Cow, marker::PhantomData, sync::Arc};
|
use std::{borrow::Cow, marker::PhantomData, sync::Arc};
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
|
/// Creates an [`Attribute`] that will set a DOM property on an element.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn prop<K, P, R>(key: K, value: P) -> Property<K, P, R>
|
pub fn prop<K, P, R>(key: K, value: P) -> Property<K, P, R>
|
||||||
where
|
where
|
||||||
|
@ -21,6 +22,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An [`Attribute`] that will set a DOM property on an element.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Property<K, P, R> {
|
pub struct Property<K, P, R> {
|
||||||
key: K,
|
key: K,
|
||||||
|
@ -139,23 +141,32 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A possible value for a DOM property.
|
||||||
pub trait IntoProperty<R: DomRenderer> {
|
pub trait IntoProperty<R: DomRenderer> {
|
||||||
|
/// The view state retained between building and rebuilding.
|
||||||
type State;
|
type State;
|
||||||
|
/// An equivalent value that can be cloned.
|
||||||
type Cloneable: IntoProperty<R> + Clone;
|
type Cloneable: IntoProperty<R> + Clone;
|
||||||
|
/// An equivalent value that can be cloned and is `'static`.
|
||||||
type CloneableOwned: IntoProperty<R> + Clone + 'static;
|
type CloneableOwned: IntoProperty<R> + Clone + 'static;
|
||||||
|
|
||||||
|
/// Adds the property on an element created from HTML.
|
||||||
fn hydrate<const FROM_SERVER: bool>(
|
fn hydrate<const FROM_SERVER: bool>(
|
||||||
self,
|
self,
|
||||||
el: &R::Element,
|
el: &R::Element,
|
||||||
key: &str,
|
key: &str,
|
||||||
) -> Self::State;
|
) -> Self::State;
|
||||||
|
|
||||||
|
/// Adds the property during client-side rendering.
|
||||||
fn build(self, el: &R::Element, key: &str) -> Self::State;
|
fn build(self, el: &R::Element, key: &str) -> Self::State;
|
||||||
|
|
||||||
|
/// Updates the property with a new value.
|
||||||
fn rebuild(self, state: &mut Self::State, key: &str);
|
fn rebuild(self, state: &mut Self::State, key: &str);
|
||||||
|
|
||||||
|
/// Converts this to a cloneable type.
|
||||||
fn into_cloneable(self) -> Self::Cloneable;
|
fn into_cloneable(self) -> Self::Cloneable;
|
||||||
|
|
||||||
|
/// Converts this to a cloneable, owned type.
|
||||||
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,9 @@ use crate::{
|
||||||
renderer::DomRenderer,
|
renderer::DomRenderer,
|
||||||
view::{Position, ToTemplate},
|
view::{Position, ToTemplate},
|
||||||
};
|
};
|
||||||
use std::{borrow::Cow, future::Future, marker::PhantomData, sync::Arc};
|
use std::{future::Future, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
/// Adds to the style attribute of the parent element.
|
/// Returns an [`Attribute`] that will add to an element's CSS styles.
|
||||||
///
|
|
||||||
/// This can take a plain string value, which will be assigned to the `style`
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn style<S, R>(style: S) -> Style<S, R>
|
pub fn style<S, R>(style: S) -> Style<S, R>
|
||||||
where
|
where
|
||||||
|
@ -22,6 +20,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An [`Attribute`] that will add to an element's CSS styles.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Style<S, R> {
|
pub struct Style<S, R> {
|
||||||
style: S,
|
style: S,
|
||||||
|
@ -140,42 +139,43 @@ where
|
||||||
/// Any type that can be added to the `style` attribute or set as a style in
|
/// Any type that can be added to the `style` attribute or set as a style in
|
||||||
/// the [`CssStyleDeclaration`]. This could be a plain string, or a property name-value pair.
|
/// the [`CssStyleDeclaration`]. This could be a plain string, or a property name-value pair.
|
||||||
pub trait IntoStyle<R: DomRenderer>: Send {
|
pub trait IntoStyle<R: DomRenderer>: Send {
|
||||||
|
/// The type after all async data have resolved.
|
||||||
type AsyncOutput: IntoStyle<R>;
|
type AsyncOutput: IntoStyle<R>;
|
||||||
|
/// The view state retained between building and rebuilding.
|
||||||
type State;
|
type State;
|
||||||
|
/// An equivalent value that can be cloned.
|
||||||
type Cloneable: IntoStyle<R> + Clone;
|
type Cloneable: IntoStyle<R> + Clone;
|
||||||
|
/// An equivalent value that can be cloned and is `'static`.
|
||||||
type CloneableOwned: IntoStyle<R> + Clone + 'static;
|
type CloneableOwned: IntoStyle<R> + Clone + 'static;
|
||||||
|
|
||||||
|
/// Renders the style to HTML.
|
||||||
fn to_html(self, style: &mut String);
|
fn to_html(self, style: &mut String);
|
||||||
|
|
||||||
|
/// Adds interactivity as necessary, given DOM nodes that were created from HTML that has
|
||||||
|
/// either been rendered on the server, or cloned for a `<template>`.
|
||||||
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Adds this style to the element during client-side rendering.
|
||||||
fn build(self, el: &R::Element) -> Self::State;
|
fn build(self, el: &R::Element) -> Self::State;
|
||||||
|
|
||||||
|
/// Updates the value.
|
||||||
fn rebuild(self, state: &mut Self::State);
|
fn rebuild(self, state: &mut Self::State);
|
||||||
|
|
||||||
|
/// Converts this to a cloneable type.
|
||||||
fn into_cloneable(self) -> Self::Cloneable;
|
fn into_cloneable(self) -> Self::Cloneable;
|
||||||
|
|
||||||
|
/// Converts this to a cloneable, owned type.
|
||||||
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
||||||
|
|
||||||
|
/// “Runs” the attribute without other side effects. For primitive types, this is a no-op. For
|
||||||
|
/// reactive types, this can be used to gather data about reactivity or about asynchronous data
|
||||||
|
/// that needs to be loaded.
|
||||||
fn dry_resolve(&mut self);
|
fn dry_resolve(&mut self);
|
||||||
|
|
||||||
|
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait StylePropertyValue<R: DomRenderer> {
|
|
||||||
type State;
|
|
||||||
|
|
||||||
fn to_html(self, name: &str, style: &mut String);
|
|
||||||
|
|
||||||
fn hydrate<const FROM_SERVER: bool>(
|
|
||||||
self,
|
|
||||||
name: Cow<'static, str>,
|
|
||||||
el: &R::Element,
|
|
||||||
) -> Self::State;
|
|
||||||
|
|
||||||
fn rebuild(self, name: Cow<'static, str>, state: &mut Self::State);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, R> IntoStyle<R> for &'a str
|
impl<'a, R> IntoStyle<R> for &'a str
|
||||||
where
|
where
|
||||||
R: DomRenderer,
|
R: DomRenderer,
|
||||||
|
|
|
@ -4,6 +4,11 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
/// Hydration works by walking over the DOM, adding interactivity as needed.
|
||||||
|
///
|
||||||
|
/// This cursor tracks the location in the DOM that is currently being hydrated. Each that type
|
||||||
|
/// implements [`RenderHtml`](crate::view::RenderHtml) knows how to advance the cursor to access
|
||||||
|
/// the nodes it needs.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Cursor<R: Renderer>(Rc<RefCell<R::Node>>);
|
pub struct Cursor<R: Renderer>(Rc<RefCell<R::Node>>);
|
||||||
|
|
||||||
|
@ -19,14 +24,19 @@ where
|
||||||
|
|
||||||
R::Element: AsRef<R::Node>,
|
R::Element: AsRef<R::Node>,
|
||||||
{
|
{
|
||||||
|
/// Creates a new cursor starting at the root element.
|
||||||
pub fn new(root: R::Element) -> Self {
|
pub fn new(root: R::Element) -> Self {
|
||||||
Self(Rc::new(RefCell::new(root.as_ref().clone())))
|
Self(Rc::new(RefCell::new(root.as_ref().clone())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the node at which the cursor is currently located.
|
||||||
pub fn current(&self) -> R::Node {
|
pub fn current(&self) -> R::Node {
|
||||||
self.0.borrow().clone()
|
self.0.borrow().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Advances to the next child of the node at which the cursor is located.
|
||||||
|
///
|
||||||
|
/// Does nothing if there is no child.
|
||||||
pub fn child(&self) {
|
pub fn child(&self) {
|
||||||
//crate::log("advancing to next child of ");
|
//crate::log("advancing to next child of ");
|
||||||
//R::log_node(&self.current());
|
//R::log_node(&self.current());
|
||||||
|
@ -39,6 +49,9 @@ where
|
||||||
//R::log_node(&self.current());
|
//R::log_node(&self.current());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Advances to the next sibling of the node at which the cursor is located.
|
||||||
|
///
|
||||||
|
/// Does nothing if there is no sibling.
|
||||||
pub fn sibling(&self) {
|
pub fn sibling(&self) {
|
||||||
//crate::log("advancing to next sibling of ");
|
//crate::log("advancing to next sibling of ");
|
||||||
//R::log_node(&self.current());
|
//R::log_node(&self.current());
|
||||||
|
@ -51,6 +64,9 @@ where
|
||||||
//R::log_node(&self.current());
|
//R::log_node(&self.current());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Moves to the parent of the node at which the cursor is located.
|
||||||
|
///
|
||||||
|
/// Does nothing if there is no parent.
|
||||||
pub fn parent(&self) {
|
pub fn parent(&self) {
|
||||||
let mut inner = self.0.borrow_mut();
|
let mut inner = self.0.borrow_mut();
|
||||||
if let Some(node) = R::get_parent(&*inner) {
|
if let Some(node) = R::get_parent(&*inner) {
|
||||||
|
@ -58,10 +74,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the cursor to some node.
|
||||||
pub fn set(&self, node: R::Node) {
|
pub fn set(&self, node: R::Node) {
|
||||||
*self.0.borrow_mut() = node;
|
*self.0.borrow_mut() = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Advances to the next placeholder node.
|
||||||
pub fn next_placeholder(&self, position: &PositionState) -> R::Placeholder {
|
pub fn next_placeholder(&self, position: &PositionState) -> R::Placeholder {
|
||||||
//crate::dom::log("looking for placeholder after");
|
//crate::dom::log("looking for placeholder after");
|
||||||
//R::log_node(&self.current());
|
//R::log_node(&self.current());
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
//! Allows rendering user interfaces based on a statically-typed view tree.
|
||||||
|
//!
|
||||||
|
//! This view tree is generic over rendering backends, and agnostic about reactivity/change
|
||||||
|
//! detection.
|
||||||
|
|
||||||
#![allow(incomplete_features)] // yolo
|
#![allow(incomplete_features)] // yolo
|
||||||
#![cfg_attr(feature = "nightly", feature(adt_const_params))]
|
#![cfg_attr(feature = "nightly", feature(adt_const_params))]
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
/// Commonly-used traits.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
#[cfg(feature = "reactive_graph")]
|
|
||||||
pub use crate::reactive_graph::FutureViewExt;
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
html::{
|
html::{
|
||||||
attribute::{
|
attribute::{
|
||||||
|
@ -29,30 +34,38 @@ pub mod prelude {
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
use web_sys::Node;
|
use web_sys::Node;
|
||||||
|
|
||||||
|
/// Helpers for interacting with the DOM.
|
||||||
pub mod dom;
|
pub mod dom;
|
||||||
|
/// Types for building a statically-typed HTML view tree.
|
||||||
pub mod html;
|
pub mod html;
|
||||||
|
/// Supports adding interactivity to HTML.
|
||||||
pub mod hydration;
|
pub mod hydration;
|
||||||
|
/// Types for MathML.
|
||||||
pub mod mathml;
|
pub mod mathml;
|
||||||
|
/// Defines various backends that can render views.
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
|
/// Rendering views to HTML.
|
||||||
pub mod ssr;
|
pub mod ssr;
|
||||||
|
/// Types for SVG.
|
||||||
pub mod svg;
|
pub mod svg;
|
||||||
|
/// Core logic for manipulating views.
|
||||||
pub mod view;
|
pub mod view;
|
||||||
|
|
||||||
pub use either_of as either;
|
pub use either_of as either;
|
||||||
#[cfg(feature = "islands")]
|
#[cfg(feature = "islands")]
|
||||||
|
#[doc(hidden)]
|
||||||
pub use wasm_bindgen;
|
pub use wasm_bindgen;
|
||||||
#[cfg(feature = "islands")]
|
#[cfg(feature = "islands")]
|
||||||
|
#[doc(hidden)]
|
||||||
pub use web_sys;
|
pub use web_sys;
|
||||||
|
|
||||||
|
/// View implementations for the `oco_ref` crate (cheaply-cloned string types).
|
||||||
#[cfg(feature = "oco")]
|
#[cfg(feature = "oco")]
|
||||||
pub mod oco;
|
pub mod oco;
|
||||||
|
/// View implementations for the `reactive_graph` crate.
|
||||||
#[cfg(feature = "reactive_graph")]
|
#[cfg(feature = "reactive_graph")]
|
||||||
pub mod reactive_graph;
|
pub mod reactive_graph;
|
||||||
|
|
||||||
pub fn log(text: &str) {
|
|
||||||
web_sys::console::log_1(&JsValue::from_str(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait UnwrapOrDebug {
|
pub(crate) trait UnwrapOrDebug {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
@ -118,6 +131,7 @@ impl<T> UnwrapOrDebug for Result<T, JsValue> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! or_debug {
|
macro_rules! or_debug {
|
||||||
($action:expr, $el:expr, $label:literal) => {
|
($action:expr, $el:expr, $label:literal) => {
|
||||||
|
@ -129,6 +143,7 @@ macro_rules! or_debug {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! ok_or_debug {
|
macro_rules! ok_or_debug {
|
||||||
($action:expr, $el:expr, $label:literal) => {
|
($action:expr, $el:expr, $label:literal) => {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use std::{fmt::Debug, marker::PhantomData};
|
||||||
macro_rules! mathml_global {
|
macro_rules! mathml_global {
|
||||||
($tag:ty, $attr:ty) => {
|
($tag:ty, $attr:ty) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
|
/// A MathML attribute.
|
||||||
pub fn $attr<V>(self, value: V) -> HtmlElement <
|
pub fn $attr<V>(self, value: V) -> HtmlElement <
|
||||||
[<$tag:camel>],
|
[<$tag:camel>],
|
||||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V, Rndr>>,
|
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V, Rndr>>,
|
||||||
|
@ -47,6 +48,7 @@ macro_rules! mathml_elements {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
$(
|
$(
|
||||||
// `tag()` function
|
// `tag()` function
|
||||||
|
/// A MathML element.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn $tag<Rndr>() -> HtmlElement<[<$tag:camel>], (), (), Rndr>
|
pub fn $tag<Rndr>() -> HtmlElement<[<$tag:camel>], (), (), Rndr>
|
||||||
where
|
where
|
||||||
|
@ -62,6 +64,7 @@ macro_rules! mathml_elements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A MathML element.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct [<$tag:camel>];
|
pub struct [<$tag:camel>];
|
||||||
|
|
||||||
|
@ -81,6 +84,7 @@ macro_rules! mathml_elements {
|
||||||
mathml_global!($tag, scriptlevel);
|
mathml_global!($tag, scriptlevel);
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
/// A MathML attribute.
|
||||||
pub fn $attr<V>(self, value: V) -> HtmlElement <
|
pub fn $attr<V>(self, value: V) -> HtmlElement <
|
||||||
[<$tag:camel>],
|
[<$tag:camel>],
|
||||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V, Rndr>>,
|
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V, Rndr>>,
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use oco_ref::Oco;
|
use oco_ref::Oco;
|
||||||
|
|
||||||
|
/// Retained view state for [`Oco`].
|
||||||
pub struct OcoStrState<R: Renderer> {
|
pub struct OcoStrState<R: Renderer> {
|
||||||
node: R::Text,
|
node: R::Text,
|
||||||
str: Oco<'static, str>,
|
str: Oco<'static, str>,
|
||||||
|
|
|
@ -20,6 +20,7 @@ use std::{
|
||||||
mod class;
|
mod class;
|
||||||
mod guards;
|
mod guards;
|
||||||
mod inner_html;
|
mod inner_html;
|
||||||
|
/// Provides a reactive [`NodeRef`](node_ref::NodeRef) type.
|
||||||
pub mod node_ref;
|
pub mod node_ref;
|
||||||
mod owned;
|
mod owned;
|
||||||
mod property;
|
mod property;
|
||||||
|
@ -78,6 +79,8 @@ where
|
||||||
old.unmount();
|
old.unmount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for a [`RenderEffect`].
|
||||||
pub struct RenderEffectState<T: 'static>(Option<RenderEffect<T>>);
|
pub struct RenderEffectState<T: 'static>(Option<RenderEffect<T>>);
|
||||||
|
|
||||||
impl<T> From<RenderEffect<T>> for RenderEffectState<T> {
|
impl<T> From<RenderEffect<T>> for RenderEffectState<T> {
|
||||||
|
@ -359,7 +362,9 @@ where
|
||||||
|
|
||||||
fn to_html(self, _key: &str, _buf: &mut String) {
|
fn to_html(self, _key: &str, _buf: &mut String) {
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
tracing::warn!("Suspended attributes cannot be used outside Suspense.");
|
tracing::error!(
|
||||||
|
"Suspended attributes cannot be used outside Suspense."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_template(_key: &str, _buf: &mut String) {}
|
fn to_template(_key: &str, _buf: &mut String) {}
|
||||||
|
@ -411,12 +416,12 @@ where
|
||||||
|
|
||||||
fn into_cloneable(self) -> Self::Cloneable {
|
fn into_cloneable(self) -> Self::Cloneable {
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
tracing::warn!("Suspended attributes cannot be spread");
|
tracing::error!("Suspended attributes cannot be spread");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_cloneable_owned(self) -> Self::CloneableOwned {
|
fn into_cloneable_owned(self) -> Self::CloneableOwned {
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
tracing::warn!("Suspended attributes cannot be spread");
|
tracing::error!("Suspended attributes cannot be spread");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dry_resolve(&mut self) {}
|
fn dry_resolve(&mut self) {}
|
||||||
|
@ -426,13 +431,18 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A reactive function that can be shared across multiple locations and across threads.
|
||||||
pub type SharedReactiveFunction<T> = Arc<Mutex<dyn FnMut() -> T + Send>>;
|
pub type SharedReactiveFunction<T> = Arc<Mutex<dyn FnMut() -> T + Send>>;
|
||||||
|
|
||||||
|
/// A reactive view function.
|
||||||
pub trait ReactiveFunction: Send + 'static {
|
pub trait ReactiveFunction: Send + 'static {
|
||||||
|
/// The return type of the function.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
/// Call the function.
|
||||||
fn invoke(&mut self) -> Self::Output;
|
fn invoke(&mut self) -> Self::Output;
|
||||||
|
|
||||||
|
/// Converts the function into a cloneable, shared type.
|
||||||
fn into_shared(self) -> Arc<Mutex<dyn FnMut() -> Self::Output + Send>>;
|
fn into_shared(self) -> Arc<Mutex<dyn FnMut() -> Self::Output + Send>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ use reactive_graph::{
|
||||||
use send_wrapper::SendWrapper;
|
use send_wrapper::SendWrapper;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
/// A reactive reference to a DOM node that can be used with the `node_ref` attribute.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NodeRef<E>(RwSignal<Option<SendWrapper<E::Output>>>)
|
pub struct NodeRef<E>(RwSignal<Option<SendWrapper<E::Output>>>)
|
||||||
where
|
where
|
||||||
|
@ -20,6 +21,7 @@ where
|
||||||
E: ElementType,
|
E: ElementType,
|
||||||
E::Output: 'static,
|
E::Output: 'static,
|
||||||
{
|
{
|
||||||
|
/// Creates a new node reference.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(RwSignal::new(None))
|
Self(RwSignal::new(None))
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
||||||
use reactive_graph::{computed::ScopedFuture, owner::Owner};
|
use reactive_graph::{computed::ScopedFuture, owner::Owner};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// A view wrapper that sets the reactive [`Owner`] to a particular owner whenever it is rendered.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct OwnedView<T, R> {
|
pub struct OwnedView<T, R> {
|
||||||
owner: Owner,
|
owner: Owner,
|
||||||
|
@ -37,6 +38,7 @@ impl<T, R> OwnedView<T, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for an [`OwnedView`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct OwnedViewState<T, R>
|
pub struct OwnedViewState<T, R>
|
||||||
where
|
where
|
||||||
|
|
|
@ -19,25 +19,7 @@ use reactive_graph::{
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, fmt::Debug, future::Future, pin::Pin, rc::Rc};
|
use std::{cell::RefCell, fmt::Debug, future::Future, pin::Pin, rc::Rc};
|
||||||
|
|
||||||
pub trait FutureViewExt: Sized {
|
/// A suspended `Future`, which can be used in the view.
|
||||||
fn wait(self) -> Suspend<Self>
|
|
||||||
where
|
|
||||||
Self: Future,
|
|
||||||
{
|
|
||||||
Suspend(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> FutureViewExt for F where F: Future + Sized {}
|
|
||||||
|
|
||||||
/* // TODO remove in favor of Suspend()?
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! suspend {
|
|
||||||
($fut:expr) => {
|
|
||||||
move || $crate::prelude::FutureViewExt::wait(async move { $fut })
|
|
||||||
};
|
|
||||||
}*/
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Suspend<Fut>(pub Fut);
|
pub struct Suspend<Fut>(pub Fut);
|
||||||
|
|
||||||
|
@ -47,6 +29,7 @@ impl<Fut> Debug for Suspend<Fut> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for [`Suspend`].
|
||||||
pub struct SuspendState<T, Rndr>
|
pub struct SuspendState<T, Rndr>
|
||||||
where
|
where
|
||||||
T: Render<Rndr>,
|
T: Render<Rndr>,
|
||||||
|
|
|
@ -14,6 +14,7 @@ use web_sys::{
|
||||||
Event, HtmlElement, HtmlTemplateElement, Node, Text,
|
Event, HtmlElement, HtmlTemplateElement, Node, Text,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A [`Renderer`] that uses `web-sys` to manipulate DOM elements in the browser.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Dom;
|
pub struct Dom;
|
||||||
|
|
||||||
|
@ -37,7 +38,12 @@ impl Renderer for Dom {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_placeholder() -> Self::Placeholder {
|
fn create_placeholder() -> Self::Placeholder {
|
||||||
document().create_comment("")
|
thread_local! {
|
||||||
|
static COMMENT: Lazy<Comment> = Lazy::new(|| {
|
||||||
|
document().create_comment("")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
COMMENT.with(|n| n.clone_node().unwrap().unchecked_into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace"))]
|
||||||
|
|
|
@ -13,22 +13,31 @@ use slotmap::{new_key_type, SlotMap};
|
||||||
use std::{borrow::Cow, cell::RefCell, collections::HashMap, rc::Rc};
|
use std::{borrow::Cow, cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
|
/// A [`Renderer`] that uses a mock DOM structure running in Rust code.
|
||||||
|
///
|
||||||
|
/// This is intended as a rendering background that can be used to test component logic, without
|
||||||
|
/// running a browser.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MockDom;
|
pub struct MockDom;
|
||||||
|
|
||||||
new_key_type! {
|
new_key_type! {
|
||||||
struct NodeId;
|
/// A unique identifier for a mock DOM node.
|
||||||
|
pub struct NodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A mock DOM node.
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub struct Node(NodeId);
|
pub struct Node(NodeId);
|
||||||
|
|
||||||
|
/// A mock element.
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub struct Element(Node);
|
pub struct Element(Node);
|
||||||
|
|
||||||
|
/// A mock text node.
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub struct Text(Node);
|
pub struct Text(Node);
|
||||||
|
|
||||||
|
/// A mock comment node.
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
pub struct Placeholder(Node);
|
pub struct Placeholder(Node);
|
||||||
|
|
||||||
|
@ -56,6 +65,7 @@ impl AsRef<Node> for Placeholder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tests whether two nodes are references to the same underlying node.
|
||||||
pub fn node_eq(a: impl AsRef<Node>, b: impl AsRef<Node>) -> bool {
|
pub fn node_eq(a: impl AsRef<Node>, b: impl AsRef<Node>) -> bool {
|
||||||
a.as_ref() == b.as_ref()
|
a.as_ref() == b.as_ref()
|
||||||
}
|
}
|
||||||
|
@ -79,6 +89,7 @@ impl From<Placeholder> for Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element {
|
impl Element {
|
||||||
|
/// Outputs an HTML form of the element, for testing and debugging purposes.
|
||||||
pub fn to_debug_html(&self) -> String {
|
pub fn to_debug_html(&self) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.debug_html(&mut buf);
|
self.debug_html(&mut buf);
|
||||||
|
@ -86,9 +97,12 @@ impl Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The DOM data associated with a particular node.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct NodeData {
|
pub struct NodeData {
|
||||||
parent: Option<NodeId>,
|
/// The node's parent.
|
||||||
|
pub parent: Option<NodeId>,
|
||||||
|
/// The node itself.
|
||||||
pub ty: NodeType,
|
pub ty: NodeType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,10 +167,12 @@ impl DebugHtml for NodeData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The mock DOM document.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Document(Rc<RefCell<SlotMap<NodeId, NodeData>>>);
|
pub struct Document(Rc<RefCell<SlotMap<NodeId, NodeData>>>);
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
|
/// Creates a new document.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Document(Default::default())
|
Document(Default::default())
|
||||||
}
|
}
|
||||||
|
@ -180,6 +196,7 @@ impl Document {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resets the document's contents.
|
||||||
pub fn reset(&self) {
|
pub fn reset(&self) {
|
||||||
self.0.borrow_mut().clear();
|
self.0.borrow_mut().clear();
|
||||||
}
|
}
|
||||||
|
@ -295,18 +312,26 @@ thread_local! {
|
||||||
static DOCUMENT: Document = Document::new();
|
static DOCUMENT: Document = Document::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the global document.
|
||||||
pub fn document() -> Document {
|
pub fn document() -> Document {
|
||||||
DOCUMENT.with(Clone::clone)
|
DOCUMENT.with(Clone::clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The type of mock DOM node.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum NodeType {
|
pub enum NodeType {
|
||||||
|
/// A text node.
|
||||||
Text(String),
|
Text(String),
|
||||||
|
/// An element.
|
||||||
Element {
|
Element {
|
||||||
|
/// The HTML tag name.
|
||||||
tag: Cow<'static, str>,
|
tag: Cow<'static, str>,
|
||||||
|
/// The attributes.
|
||||||
attrs: HashMap<String, String>,
|
attrs: HashMap<String, String>,
|
||||||
|
/// The element's children.
|
||||||
children: Vec<Node>,
|
children: Vec<Node>,
|
||||||
},
|
},
|
||||||
|
/// A placeholder.
|
||||||
Placeholder,
|
Placeholder,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,12 @@ use crate::{
|
||||||
use std::{borrow::Cow, fmt::Debug};
|
use std::{borrow::Cow, fmt::Debug};
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
|
/// A DOM renderer.
|
||||||
pub mod dom;
|
pub mod dom;
|
||||||
#[cfg(feature = "testing")]
|
#[cfg(feature = "testing")]
|
||||||
|
/// A renderer based on a mock DOM.
|
||||||
pub mod mock_dom;
|
pub mod mock_dom;
|
||||||
|
/// A DOM renderer optimized for element creation.
|
||||||
#[cfg(feature = "sledgehammer")]
|
#[cfg(feature = "sledgehammer")]
|
||||||
pub mod sledgehammer;
|
pub mod sledgehammer;
|
||||||
|
|
||||||
|
@ -38,6 +41,7 @@ pub trait Renderer: Send + Sized + Debug + 'static {
|
||||||
+ Clone
|
+ Clone
|
||||||
+ 'static;
|
+ 'static;
|
||||||
|
|
||||||
|
/// Interns a string slice, if that is available on this platform and useful as an optimization.
|
||||||
fn intern(text: &str) -> &str;
|
fn intern(text: &str) -> &str;
|
||||||
|
|
||||||
/// Creates a new element node.
|
/// Creates a new element node.
|
||||||
|
@ -123,6 +127,7 @@ pub trait Renderer: Send + Sized + Debug + 'static {
|
||||||
/// Returns the next sibling of the given node, if any.
|
/// Returns the next sibling of the given node, if any.
|
||||||
fn next_sibling(node: &Self::Node) -> Option<Self::Node>;
|
fn next_sibling(node: &Self::Node) -> Option<Self::Node>;
|
||||||
|
|
||||||
|
/// Logs the given node in a platform-appropriate way.
|
||||||
fn log_node(node: &Self::Node);
|
fn log_node(node: &Self::Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +213,7 @@ pub trait DomRenderer: Renderer {
|
||||||
fn get_template<V>() -> Self::TemplateElement
|
fn get_template<V>() -> Self::TemplateElement
|
||||||
where
|
where
|
||||||
V: ToTemplate + 'static;
|
V: ToTemplate + 'static;
|
||||||
|
/// Deeply clones a template.
|
||||||
fn clone_template(tpl: &Self::TemplateElement) -> Self::Element;
|
fn clone_template(tpl: &Self::TemplateElement) -> Self::Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,5 +227,6 @@ pub trait CastFrom<T>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
/// Casts a node from one type to another.
|
||||||
fn cast_from(source: T) -> Option<Self>;
|
fn cast_from(source: T) -> Option<Self>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use super::{CastFrom, DomRenderer, Renderer};
|
#![allow(missing_docs)] // Allow missing docs for experimental backend
|
||||||
|
|
||||||
|
use super::{CastFrom, DomRenderer, RemoveEventHandler, Renderer};
|
||||||
use crate::{
|
use crate::{
|
||||||
dom::window,
|
dom::window,
|
||||||
view::{Mountable, ToTemplate},
|
view::{Mountable, ToTemplate},
|
||||||
|
@ -374,7 +376,7 @@ impl DomRenderer for Sledgehammer {
|
||||||
el: &Self::Element,
|
el: &Self::Element,
|
||||||
name: &str,
|
name: &str,
|
||||||
cb: Box<dyn FnMut(Self::Event)>,
|
cb: Box<dyn FnMut(Self::Event)>,
|
||||||
) -> Box<dyn FnOnce(&Self::Element) + Send> {
|
) -> RemoveEventHandler<Self::Element> {
|
||||||
let cb = wasm_bindgen::closure::Closure::wrap(cb).into_js_value();
|
let cb = wasm_bindgen::closure::Closure::wrap(cb).into_js_value();
|
||||||
CHANNEL.with_borrow_mut(|channel| {
|
CHANNEL.with_borrow_mut(|channel| {
|
||||||
channel.add_listener(el.0 .0, name);
|
channel.add_listener(el.0 .0, name);
|
||||||
|
@ -383,7 +385,7 @@ impl DomRenderer for Sledgehammer {
|
||||||
});
|
});
|
||||||
|
|
||||||
// return the remover
|
// return the remover
|
||||||
Box::new(move |_el| todo!())
|
RemoveEventHandler(Box::new(move |_el| todo!()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event_target<T>(_ev: &Self::Event) -> T
|
fn event_target<T>(_ev: &Self::Event) -> T
|
||||||
|
@ -404,7 +406,7 @@ impl DomRenderer for Sledgehammer {
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
delegation_key: Cow<'static, str>,
|
delegation_key: Cow<'static, str>,
|
||||||
cb: Box<dyn FnMut(Self::Event)>,
|
cb: Box<dyn FnMut(Self::Event)>,
|
||||||
) -> Box<dyn FnOnce(&Self::Element) + Send> {
|
) -> RemoveEventHandler<Self::Element> {
|
||||||
let cb = Closure::wrap(cb).into_js_value();
|
let cb = Closure::wrap(cb).into_js_value();
|
||||||
CHANNEL.with_borrow_mut(|channel| {
|
CHANNEL.with_borrow_mut(|channel| {
|
||||||
channel.set_property(el.0 .0, &delegation_key);
|
channel.set_property(el.0 .0, &delegation_key);
|
||||||
|
@ -481,7 +483,7 @@ impl DomRenderer for Sledgehammer {
|
||||||
});
|
});
|
||||||
|
|
||||||
// return the remover
|
// return the remover
|
||||||
Box::new(move |_el| todo!())
|
RemoveEventHandler(Box::new(move |_el| todo!()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn class_list(el: &Self::Element) -> Self::ClassList {
|
fn class_list(el: &Self::Element) -> Self::ClassList {
|
||||||
|
|
|
@ -12,10 +12,11 @@ use std::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Manages streaming HTML rendering for the response to a single request.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct StreamBuilder {
|
pub struct StreamBuilder {
|
||||||
sync_buf: String,
|
sync_buf: String,
|
||||||
pub chunks: VecDeque<StreamChunk>,
|
pub(crate) chunks: VecDeque<StreamChunk>,
|
||||||
pending: Option<ChunkFuture>,
|
pending: Option<ChunkFuture>,
|
||||||
pending_ooo: VecDeque<PinnedFuture<OooChunk>>,
|
pending_ooo: VecDeque<PinnedFuture<OooChunk>>,
|
||||||
id: Option<Vec<u16>>,
|
id: Option<Vec<u16>>,
|
||||||
|
@ -25,10 +26,12 @@ type PinnedFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
|
||||||
type ChunkFuture = PinnedFuture<VecDeque<StreamChunk>>;
|
type ChunkFuture = PinnedFuture<VecDeque<StreamChunk>>;
|
||||||
|
|
||||||
impl StreamBuilder {
|
impl StreamBuilder {
|
||||||
|
/// Creates a new HTML stream.
|
||||||
pub fn new(id: Option<Vec<u16>>) -> Self {
|
pub fn new(id: Option<Vec<u16>>) -> Self {
|
||||||
Self::with_capacity(0, id)
|
Self::with_capacity(0, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new stream with a given capacity in the synchronous buffer and an identifier.
|
||||||
pub fn with_capacity(capacity: usize, id: Option<Vec<u16>>) -> Self {
|
pub fn with_capacity(capacity: usize, id: Option<Vec<u16>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
|
@ -37,14 +40,17 @@ impl StreamBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reserves additional space in the synchronous buffer.
|
||||||
pub fn reserve(&mut self, additional: usize) {
|
pub fn reserve(&mut self, additional: usize) {
|
||||||
self.sync_buf.reserve(additional);
|
self.sync_buf.reserve(additional);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes text into the synchronous buffer.
|
||||||
pub fn push_sync(&mut self, string: &str) {
|
pub fn push_sync(&mut self, string: &str) {
|
||||||
self.sync_buf.push_str(string);
|
self.sync_buf.push_str(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes an async block into the stream.
|
||||||
pub fn push_async(
|
pub fn push_async(
|
||||||
&mut self,
|
&mut self,
|
||||||
fut: impl Future<Output = VecDeque<StreamChunk>> + Send + 'static,
|
fut: impl Future<Output = VecDeque<StreamChunk>> + Send + 'static,
|
||||||
|
@ -59,10 +65,12 @@ impl StreamBuilder {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mutates the synchronous buffer.
|
||||||
pub fn with_buf(&mut self, fun: impl FnOnce(&mut String)) {
|
pub fn with_buf(&mut self, fun: impl FnOnce(&mut String)) {
|
||||||
fun(&mut self.sync_buf)
|
fun(&mut self.sync_buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes all chunks currently available in the stream, including the synchronous buffer.
|
||||||
pub fn take_chunks(&mut self) -> VecDeque<StreamChunk> {
|
pub fn take_chunks(&mut self) -> VecDeque<StreamChunk> {
|
||||||
let sync = mem::take(&mut self.sync_buf);
|
let sync = mem::take(&mut self.sync_buf);
|
||||||
if !sync.is_empty() {
|
if !sync.is_empty() {
|
||||||
|
@ -71,11 +79,13 @@ impl StreamBuilder {
|
||||||
mem::take(&mut self.chunks)
|
mem::take(&mut self.chunks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Appends another stream to this one.
|
||||||
pub fn append(&mut self, mut other: StreamBuilder) {
|
pub fn append(&mut self, mut other: StreamBuilder) {
|
||||||
self.chunks.append(&mut other.chunks);
|
self.chunks.append(&mut other.chunks);
|
||||||
self.sync_buf.push_str(&other.sync_buf);
|
self.sync_buf.push_str(&other.sync_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Completes the stream.
|
||||||
pub fn finish(mut self) -> Self {
|
pub fn finish(mut self) -> Self {
|
||||||
let sync_buf_remaining = mem::take(&mut self.sync_buf);
|
let sync_buf_remaining = mem::take(&mut self.sync_buf);
|
||||||
if sync_buf_remaining.is_empty() {
|
if sync_buf_remaining.is_empty() {
|
||||||
|
@ -89,6 +99,7 @@ impl StreamBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Out-of-Order Streaming
|
// Out-of-Order Streaming
|
||||||
|
/// Pushes a fallback for out-of-order streaming.
|
||||||
pub fn push_fallback<View, Rndr>(
|
pub fn push_fallback<View, Rndr>(
|
||||||
&mut self,
|
&mut self,
|
||||||
fallback: View,
|
fallback: View,
|
||||||
|
@ -103,16 +114,19 @@ impl StreamBuilder {
|
||||||
*position = Position::NextChild;
|
*position = Position::NextChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Increments the chunk ID.
|
||||||
pub fn next_id(&mut self) {
|
pub fn next_id(&mut self) {
|
||||||
if let Some(last) = self.id.as_mut().and_then(|ids| ids.last_mut()) {
|
if let Some(last) = self.id.as_mut().and_then(|ids| ids.last_mut()) {
|
||||||
*last += 1;
|
*last += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the current ID.
|
||||||
pub fn clone_id(&self) -> Option<Vec<u16>> {
|
pub fn clone_id(&self) -> Option<Vec<u16>> {
|
||||||
self.id.clone()
|
self.id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an ID that is a child of the current one.
|
||||||
pub fn child_id(&self) -> Option<Vec<u16>> {
|
pub fn child_id(&self) -> Option<Vec<u16>> {
|
||||||
let mut child = self.id.clone();
|
let mut child = self.id.clone();
|
||||||
if let Some(child) = child.as_mut() {
|
if let Some(child) = child.as_mut() {
|
||||||
|
@ -121,6 +135,7 @@ impl StreamBuilder {
|
||||||
child
|
child
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts a marker for the current out-of-order chunk.
|
||||||
pub fn write_chunk_marker(&mut self, opening: bool) {
|
pub fn write_chunk_marker(&mut self, opening: bool) {
|
||||||
if let Some(id) = &self.id {
|
if let Some(id) = &self.id {
|
||||||
self.sync_buf.reserve(11 + (id.len() * 2));
|
self.sync_buf.reserve(11 + (id.len() * 2));
|
||||||
|
@ -136,6 +151,7 @@ impl StreamBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Injects an out-of-order chunk into the stream.
|
||||||
pub fn push_async_out_of_order<View, Rndr>(
|
pub fn push_async_out_of_order<View, Rndr>(
|
||||||
&mut self,
|
&mut self,
|
||||||
view: impl Future<Output = Option<View>> + Send + 'static,
|
view: impl Future<Output = Option<View>> + Send + 'static,
|
||||||
|
@ -193,16 +209,23 @@ impl Debug for StreamBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A chunk of the HTML stream.
|
||||||
pub enum StreamChunk {
|
pub enum StreamChunk {
|
||||||
|
/// Some synchronously-available HTML.
|
||||||
Sync(String),
|
Sync(String),
|
||||||
|
/// The chunk can be rendered asynchronously in order.
|
||||||
Async {
|
Async {
|
||||||
|
/// A collection of in-order chunks.
|
||||||
chunks: PinnedFuture<VecDeque<StreamChunk>>,
|
chunks: PinnedFuture<VecDeque<StreamChunk>>,
|
||||||
},
|
},
|
||||||
|
/// The chunk can be rendered asynchronously out of order.
|
||||||
OutOfOrder {
|
OutOfOrder {
|
||||||
|
/// A collection of out-of-order chunks
|
||||||
chunks: PinnedFuture<OooChunk>,
|
chunks: PinnedFuture<OooChunk>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A chunk of the out-of-order stream.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OooChunk {
|
pub struct OooChunk {
|
||||||
id: String,
|
id: String,
|
||||||
|
@ -211,6 +234,7 @@ pub struct OooChunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OooChunk {
|
impl OooChunk {
|
||||||
|
/// Pushes an opening `<template>` tag into the buffer.
|
||||||
pub fn push_start(id: &str, buf: &mut String) {
|
pub fn push_start(id: &str, buf: &mut String) {
|
||||||
buf.push_str("<template id=\"");
|
buf.push_str("<template id=\"");
|
||||||
buf.push_str(id);
|
buf.push_str(id);
|
||||||
|
@ -218,6 +242,7 @@ impl OooChunk {
|
||||||
buf.push_str("\">");
|
buf.push_str("\">");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes a closing `</template>` and update script into the buffer.
|
||||||
pub fn push_end(replace: bool, id: &str, buf: &mut String) {
|
pub fn push_end(replace: bool, id: &str, buf: &mut String) {
|
||||||
buf.push_str("</template>");
|
buf.push_str("</template>");
|
||||||
|
|
||||||
|
@ -411,6 +436,7 @@ impl Stream for StreamBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -635,3 +661,4 @@ mod tests {
|
||||||
assert!(stream.next().await.is_none());
|
assert!(stream.next().await.is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -15,6 +15,7 @@ macro_rules! svg_elements {
|
||||||
($($tag:ident [$($attr:ty),*]),* $(,)?) => {
|
($($tag:ident [$($attr:ty),*]),* $(,)?) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
$(
|
$(
|
||||||
|
/// An SVG attribute.
|
||||||
// `tag()` function
|
// `tag()` function
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn $tag<Rndr>() -> HtmlElement<[<$tag:camel>], (), (), Rndr>
|
pub fn $tag<Rndr>() -> HtmlElement<[<$tag:camel>], (), (), Rndr>
|
||||||
|
@ -31,6 +32,7 @@ macro_rules! svg_elements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An SVG element.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct [<$tag:camel>];
|
pub struct [<$tag:camel>];
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,10 @@ pub trait AddAnyAttr<Rndr>
|
||||||
where
|
where
|
||||||
Rndr: Renderer,
|
Rndr: Renderer,
|
||||||
{
|
{
|
||||||
|
/// The new type once the attribute has been added.
|
||||||
type Output<SomeNewAttr: Attribute<Rndr>>: RenderHtml<Rndr>;
|
type Output<SomeNewAttr: Attribute<Rndr>>: RenderHtml<Rndr>;
|
||||||
|
|
||||||
|
/// Adds an attribute to the view.
|
||||||
fn add_any_attr<NewAttr: Attribute<Rndr>>(
|
fn add_any_attr<NewAttr: Attribute<Rndr>>(
|
||||||
self,
|
self,
|
||||||
attr: NewAttr,
|
attr: NewAttr,
|
||||||
|
@ -22,6 +24,7 @@ where
|
||||||
Self::Output<NewAttr>: RenderHtml<Rndr>;
|
Self::Output<NewAttr>: RenderHtml<Rndr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Declares that spreading attributes onto a particular type has no effect.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! no_attrs {
|
macro_rules! no_attrs {
|
||||||
($ty_name:ty) => {
|
($ty_name:ty) => {
|
||||||
|
|
|
@ -14,6 +14,16 @@ use std::{
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
|
/// A type-erased view. This can be used if control flow requires that multiple different types of
|
||||||
|
/// view must be received, and it is either impossible or too cumbersome to use the `EitherOf___`
|
||||||
|
/// enums.
|
||||||
|
///
|
||||||
|
/// It can also be used to create recursive components, which otherwise cannot return themselves
|
||||||
|
/// due to the static typing of the view tree.
|
||||||
|
///
|
||||||
|
/// Generally speaking, using `AnyView` restricts the amount of information available to the
|
||||||
|
/// compiler and should be limited to situations in which it is necessary to preserve the maximum
|
||||||
|
/// amount of type information possible.
|
||||||
pub struct AnyView<R>
|
pub struct AnyView<R>
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
|
@ -49,6 +59,7 @@ where
|
||||||
fn(Box<dyn Any>, &Cursor<R>, &PositionState) -> AnyViewState<R>,
|
fn(Box<dyn Any>, &Cursor<R>, &PositionState) -> AnyViewState<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for [`AnyView`].
|
||||||
pub struct AnyViewState<R>
|
pub struct AnyViewState<R>
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
|
@ -77,10 +88,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allows converting some view into [`AnyView`].
|
||||||
pub trait IntoAny<R>
|
pub trait IntoAny<R>
|
||||||
where
|
where
|
||||||
R: Renderer,
|
R: Renderer,
|
||||||
{
|
{
|
||||||
|
/// Converts the view into a type-erased [`AnyView`].
|
||||||
fn into_any(self) -> AnyView<R>;
|
fn into_any(self) -> AnyView<R>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,11 +198,15 @@ where
|
||||||
|
|
||||||
/// Stores each value in the view state, overwriting it only if `Some(_)` is provided.
|
/// Stores each value in the view state, overwriting it only if `Some(_)` is provided.
|
||||||
pub struct EitherKeepAlive<A, B> {
|
pub struct EitherKeepAlive<A, B> {
|
||||||
|
/// The first possibility.
|
||||||
pub a: Option<A>,
|
pub a: Option<A>,
|
||||||
|
/// The second possibility.
|
||||||
pub b: Option<B>,
|
pub b: Option<B>,
|
||||||
|
/// If `true`, then `b` will be shown.
|
||||||
pub show_b: bool,
|
pub show_b: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for [`EitherKeepAlive`].
|
||||||
pub struct EitherKeepAliveState<A, B> {
|
pub struct EitherKeepAliveState<A, B> {
|
||||||
a: Option<A>,
|
a: Option<A>,
|
||||||
b: Option<B>,
|
b: Option<B>,
|
||||||
|
@ -392,12 +396,15 @@ where
|
||||||
macro_rules! tuples {
|
macro_rules! tuples {
|
||||||
($num:literal => $($ty:ident),*) => {
|
($num:literal => $($ty:ident),*) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
|
#[doc = concat!("Retained view state for ", stringify!([<EitherOf $num>]), ".")]
|
||||||
pub struct [<EitherOf $num State>]<$($ty,)* Rndr>
|
pub struct [<EitherOf $num State>]<$($ty,)* Rndr>
|
||||||
where
|
where
|
||||||
$($ty: Render<Rndr>,)*
|
$($ty: Render<Rndr>,)*
|
||||||
Rndr: Renderer
|
Rndr: Renderer
|
||||||
{
|
{
|
||||||
|
/// Which child view state is being displayed.
|
||||||
pub state: [<EitherOf $num>]<$($ty::State,)*>,
|
pub state: [<EitherOf $num>]<$($ty::State,)*>,
|
||||||
|
/// The renderer.
|
||||||
pub rndr: PhantomData<Rndr>
|
pub rndr: PhantomData<Rndr>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ pub struct Fragment<R: Renderer> {
|
||||||
pub nodes: Vec<AnyView<R>>,
|
pub nodes: Vec<AnyView<R>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts some view into a type-erased collection of views.
|
||||||
pub trait IntoFragment<R: Renderer> {
|
pub trait IntoFragment<R: Renderer> {
|
||||||
|
/// Converts some view into a type-erased collection of views.
|
||||||
fn into_fragment(self) -> Fragment<R>;
|
fn into_fragment(self) -> Fragment<R>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
||||||
use either_of::Either;
|
use either_of::Either;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
/// Retained view state for an `Option`.
|
||||||
pub type OptionState<T, R> =
|
pub type OptionState<T, R> =
|
||||||
Either<<T as Render<R>>::State, <() as Render<R>>::State>;
|
Either<<T as Render<R>>::State, <() as Render<R>>::State>;
|
||||||
|
|
||||||
|
@ -182,6 +183,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for a `Vec<_>`.
|
||||||
pub struct VecState<T, R>
|
pub struct VecState<T, R>
|
||||||
where
|
where
|
||||||
T: Mountable<R>,
|
T: Mountable<R>,
|
||||||
|
|
|
@ -18,6 +18,7 @@ use std::{
|
||||||
|
|
||||||
type FxIndexSet<T> = IndexSet<T, BuildHasherDefault<FxHasher>>;
|
type FxIndexSet<T> = IndexSet<T, BuildHasherDefault<FxHasher>>;
|
||||||
|
|
||||||
|
/// Creates a keyed list of views.
|
||||||
pub fn keyed<T, I, K, KF, VF, V, Rndr>(
|
pub fn keyed<T, I, K, KF, VF, V, Rndr>(
|
||||||
items: I,
|
items: I,
|
||||||
key_fn: KF,
|
key_fn: KF,
|
||||||
|
@ -39,6 +40,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A keyed list of views.
|
||||||
pub struct Keyed<T, I, K, KF, VF, V, Rndr>
|
pub struct Keyed<T, I, K, KF, VF, V, Rndr>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = T>,
|
I: IntoIterator<Item = T>,
|
||||||
|
@ -53,6 +55,7 @@ where
|
||||||
rndr: PhantomData<Rndr>,
|
rndr: PhantomData<Rndr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for a keyed list.
|
||||||
pub struct KeyedState<K, V, Rndr>
|
pub struct KeyedState<K, V, Rndr>
|
||||||
where
|
where
|
||||||
K: Eq + Hash + 'static,
|
K: Eq + Hash + 'static,
|
||||||
|
|
|
@ -3,18 +3,29 @@ use crate::{hydration::Cursor, renderer::Renderer, ssr::StreamBuilder};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::{cell::RefCell, future::Future, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, future::Future, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
|
/// Add attributes to typed views.
|
||||||
pub mod add_attr;
|
pub mod add_attr;
|
||||||
|
/// A typed-erased view type.
|
||||||
pub mod any_view;
|
pub mod any_view;
|
||||||
|
/// Allows choosing between one of several views.
|
||||||
pub mod either;
|
pub mod either;
|
||||||
|
/// View rendering for `Result<_, _>` types.
|
||||||
pub mod error_boundary;
|
pub mod error_boundary;
|
||||||
|
/// A type-erased view collection.
|
||||||
pub mod fragment;
|
pub mod fragment;
|
||||||
|
/// View implementations for several iterable types.
|
||||||
pub mod iterators;
|
pub mod iterators;
|
||||||
|
/// Keyed list iteration.
|
||||||
pub mod keyed;
|
pub mod keyed;
|
||||||
mod primitives;
|
mod primitives;
|
||||||
|
/// Optimized types for static strings known at compile time.
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
pub mod static_types;
|
pub mod static_types;
|
||||||
|
/// View implementation for string types.
|
||||||
pub mod strings;
|
pub mod strings;
|
||||||
|
/// Optimizations for creating views via HTML `<template>` nodes.
|
||||||
pub mod template;
|
pub mod template;
|
||||||
|
/// View implementations for tuples.
|
||||||
pub mod tuples;
|
pub mod tuples;
|
||||||
|
|
||||||
/// The `Render` trait allows rendering something as part of the user interface.
|
/// The `Render` trait allows rendering something as part of the user interface.
|
||||||
|
@ -35,17 +46,6 @@ pub trait Render<R: Renderer>: Sized {
|
||||||
fn rebuild(self, state: &mut Self::State);
|
fn rebuild(self, state: &mut Self::State);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct NeverError;
|
|
||||||
|
|
||||||
impl core::fmt::Display for NeverError {
|
|
||||||
fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for NeverError {}
|
|
||||||
|
|
||||||
/// The `RenderHtml` trait allows rendering something to HTML, and transforming
|
/// The `RenderHtml` trait allows rendering something to HTML, and transforming
|
||||||
/// that HTML into an interactive interface.
|
/// that HTML into an interactive interface.
|
||||||
///
|
///
|
||||||
|
@ -65,11 +65,15 @@ where
|
||||||
/// The type of the view after waiting for all asynchronous data to load.
|
/// The type of the view after waiting for all asynchronous data to load.
|
||||||
type AsyncOutput: RenderHtml<R>;
|
type AsyncOutput: RenderHtml<R>;
|
||||||
|
|
||||||
|
/// The minimum length of HTML created when this view is rendered.
|
||||||
const MIN_LENGTH: usize;
|
const MIN_LENGTH: usize;
|
||||||
|
|
||||||
/// Whether this should actually exist in the DOM, if it is the child of an element.
|
/// Whether this should actually exist in the DOM, if it is the child of an element.
|
||||||
const EXISTS: bool = true;
|
const EXISTS: bool = true;
|
||||||
|
|
||||||
|
/// “Runs” the view without other side effects. For primitive types, this is a no-op. For
|
||||||
|
/// reactive types, this can be used to gather data about reactivity or about asynchronous data
|
||||||
|
/// that needs to be loaded.
|
||||||
fn dry_resolve(&mut self);
|
fn dry_resolve(&mut self);
|
||||||
|
|
||||||
/// Waits for any asynchronous sections of the view to load and returns the output.
|
/// Waits for any asynchronous sections of the view to load and returns the output.
|
||||||
|
@ -282,9 +286,13 @@ where
|
||||||
|
|
||||||
/// Allows data to be added to a static template.
|
/// Allows data to be added to a static template.
|
||||||
pub trait ToTemplate {
|
pub trait ToTemplate {
|
||||||
|
/// The HTML content of the static template.
|
||||||
const TEMPLATE: &'static str = "";
|
const TEMPLATE: &'static str = "";
|
||||||
|
/// The `class` attribute content known at compile time.
|
||||||
const CLASS: &'static str = "";
|
const CLASS: &'static str = "";
|
||||||
|
/// The `style` attribute content known at compile time.
|
||||||
const STYLE: &'static str = "";
|
const STYLE: &'static str = "";
|
||||||
|
/// The length of the template.
|
||||||
const LEN: usize = Self::TEMPLATE.as_bytes().len();
|
const LEN: usize = Self::TEMPLATE.as_bytes().len();
|
||||||
|
|
||||||
/// Renders a view type to a template. This does not take actual view data,
|
/// Renders a view type to a template. This does not take actual view data,
|
||||||
|
@ -299,35 +307,49 @@ pub trait ToTemplate {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Keeps track of what position the item currently being hydrated is in, relative to its siblings
|
||||||
|
/// and parents.
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct PositionState(Arc<RwLock<Position>>);
|
pub struct PositionState(Arc<RwLock<Position>>);
|
||||||
|
|
||||||
impl PositionState {
|
impl PositionState {
|
||||||
|
/// Creates a new position tracker.
|
||||||
pub fn new(position: Position) -> Self {
|
pub fn new(position: Position) -> Self {
|
||||||
Self(Arc::new(RwLock::new(position)))
|
Self(Arc::new(RwLock::new(position)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the current position.
|
||||||
pub fn set(&self, position: Position) {
|
pub fn set(&self, position: Position) {
|
||||||
*self.0.write() = position;
|
*self.0.write() = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the current position.
|
||||||
pub fn get(&self) -> Position {
|
pub fn get(&self) -> Position {
|
||||||
*self.0.read()
|
*self.0.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`PositionState`], which starts with the same [`Position`], but no longer
|
||||||
|
/// shares data with this `PositionState`.
|
||||||
pub fn deep_clone(&self) -> Self {
|
pub fn deep_clone(&self) -> Self {
|
||||||
let current = self.get();
|
let current = self.get();
|
||||||
Self(Arc::new(RwLock::new(current)))
|
Self(Arc::new(RwLock::new(current)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The position of this element, relative to others.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
||||||
pub enum Position {
|
pub enum Position {
|
||||||
|
/// This is the current node.
|
||||||
Current,
|
Current,
|
||||||
|
/// This is the first child of its parent.
|
||||||
#[default]
|
#[default]
|
||||||
FirstChild,
|
FirstChild,
|
||||||
|
/// This is the next child after another child.
|
||||||
NextChild,
|
NextChild,
|
||||||
|
/// This is the next child after a text node.
|
||||||
NextChildAfterText,
|
NextChildAfterText,
|
||||||
|
/// This is the only child of its parent.
|
||||||
OnlyChild,
|
OnlyChild,
|
||||||
|
/// This is the last child of its parent.
|
||||||
LastChild,
|
LastChild,
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ impl<K: AttributeKey, const V: &'static str> PartialEq for StaticAttr<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an [`Attribute`] whose key and value are both known at compile time.
|
||||||
pub fn static_attr<K: AttributeKey, const V: &'static str>() -> StaticAttr<K, V>
|
pub fn static_attr<K: AttributeKey, const V: &'static str>() -> StaticAttr<K, V>
|
||||||
{
|
{
|
||||||
StaticAttr { ty: PhantomData }
|
StaticAttr { ty: PhantomData }
|
||||||
|
@ -132,6 +133,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A static string that is known at compile time and can be optimized by including its type in the
|
||||||
|
/// view tree.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Static<const V: &'static str>;
|
pub struct Static<const V: &'static str>;
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,9 @@ no_attrs!(String);
|
||||||
no_attrs!(Arc<str>);
|
no_attrs!(Arc<str>);
|
||||||
no_attrs!(Cow<'a, str>);
|
no_attrs!(Cow<'a, str>);
|
||||||
|
|
||||||
|
/// Retained view state for `&str`.
|
||||||
pub struct StrState<'a, R: Renderer> {
|
pub struct StrState<'a, R: Renderer> {
|
||||||
pub node: R::Text,
|
pub(crate) node: R::Text,
|
||||||
str: &'a str,
|
str: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +143,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for `String`.
|
||||||
pub struct StringState<R: Renderer> {
|
pub struct StringState<R: Renderer> {
|
||||||
node: R::Text,
|
node: R::Text,
|
||||||
str: String,
|
str: String,
|
||||||
|
@ -240,6 +242,7 @@ impl<R: Renderer> Mountable<R> for StringState<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for `Rc<str>`.
|
||||||
pub struct RcStrState<R: Renderer> {
|
pub struct RcStrState<R: Renderer> {
|
||||||
node: R::Text,
|
node: R::Text,
|
||||||
str: Rc<str>,
|
str: Rc<str>,
|
||||||
|
@ -331,6 +334,7 @@ impl<R: Renderer> Mountable<R> for RcStrState<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for `Arc<str>`.
|
||||||
pub struct ArcStrState<R: Renderer> {
|
pub struct ArcStrState<R: Renderer> {
|
||||||
node: R::Text,
|
node: R::Text,
|
||||||
str: Arc<str>,
|
str: Arc<str>,
|
||||||
|
@ -426,6 +430,7 @@ impl<R: Renderer> Mountable<R> for ArcStrState<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retained view state for `Cow<'_, str>`.
|
||||||
pub struct CowStrState<'a, R: Renderer> {
|
pub struct CowStrState<'a, R: Renderer> {
|
||||||
node: R::Text,
|
node: R::Text,
|
||||||
str: Cow<'a, str>,
|
str: Cow<'a, str>,
|
||||||
|
|
|
@ -7,6 +7,11 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// A view wrapper that uses a `<template>` node to optimize DOM node creation.
|
||||||
|
///
|
||||||
|
/// Rather than creating all of the DOM nodes each time it is built, this template will create a
|
||||||
|
/// single `<template>` node once, then use `.cloneNode(true)` to clone that entire tree, and
|
||||||
|
/// hydrate it to add event listeners and interactivity for this instance.
|
||||||
pub struct ViewTemplate<V, R> {
|
pub struct ViewTemplate<V, R> {
|
||||||
view: V,
|
view: V,
|
||||||
rndr: PhantomData<R>,
|
rndr: PhantomData<R>,
|
||||||
|
@ -17,6 +22,7 @@ where
|
||||||
V: Render<R> + ToTemplate + 'static,
|
V: Render<R> + ToTemplate + 'static,
|
||||||
R: DomRenderer,
|
R: DomRenderer,
|
||||||
{
|
{
|
||||||
|
/// Creates a new view template.
|
||||||
pub fn new(view: V) -> Self {
|
pub fn new(view: V) -> Self {
|
||||||
Self {
|
Self {
|
||||||
view,
|
view,
|
||||||
|
|
Loading…
Reference in New Issue