mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
docs: add tachys docs
This commit is contained in:
parent
ddb596feb5
commit
64bc2580ff
44 changed files with 1092 additions and 345 deletions
|
@ -1,6 +1,5 @@
|
|||
use once_cell::unsync::Lazy;
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::{Document, HtmlElement, Node, Window};
|
||||
use web_sys::{Document, HtmlElement, Window};
|
||||
|
||||
thread_local! {
|
||||
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
|
||||
/// requires only one call out to JavaScript.
|
||||
///
|
||||
/// ## Panics
|
||||
/// Panics if called outside a browser environment.
|
||||
pub fn document() -> Document {
|
||||
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 {
|
||||
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)
|
||||
/// from any event.
|
||||
pub fn event_target<T>(event: &web_sys::Event) -> T
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::{
|
|||
#[cfg(feature = "ssr")]
|
||||
use std::{future::Future, pin::Pin};
|
||||
|
||||
/// A type-erased container for any [`Attribute`].
|
||||
pub struct AnyAttribute<R: Renderer> {
|
||||
type_id: TypeId,
|
||||
html_len: usize,
|
||||
|
@ -40,6 +41,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// View state for [`AnyAttribute`].
|
||||
pub struct AnyAttributeState<R>
|
||||
where
|
||||
R: Renderer,
|
||||
|
@ -50,10 +52,12 @@ where
|
|||
rndr: PhantomData<R>,
|
||||
}
|
||||
|
||||
/// Converts an [`Attribute`] into [`AnyAttribute`].
|
||||
pub trait IntoAnyAttribute<R>
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
/// Wraps the given attribute.
|
||||
fn into_any_attr(self) -> AnyAttribute<R>;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,14 @@ use crate::{
|
|||
view::add_attr::AddAnyAttr,
|
||||
};
|
||||
|
||||
/// Applies ARIA attributes to an HTML element.
|
||||
pub trait AriaAttributes<Rndr, V>
|
||||
where
|
||||
Self: Sized + AddAnyAttr<Rndr>,
|
||||
V: AttributeValue<Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
/// Identifies the currently active descendant of a composite widget.
|
||||
fn aria_activedescendant(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -17,6 +19,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -24,6 +27,7 @@ where
|
|||
self.add_any_attr(aria_atomic(value))
|
||||
}
|
||||
|
||||
/// Indicates whether user input completion suggestions are provided.
|
||||
fn aria_autocomplete(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -32,6 +36,7 @@ where
|
|||
self.add_any_attr(aria_autocomplete(value))
|
||||
}
|
||||
|
||||
/// Indicates whether an element, and its subtree, are currently being updated.
|
||||
fn aria_busy(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -39,6 +44,7 @@ where
|
|||
self.add_any_attr(aria_busy(value))
|
||||
}
|
||||
|
||||
/// Indicates the current "checked" state of checkboxes, radio buttons, and other widgets.
|
||||
fn aria_checked(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -46,6 +52,7 @@ where
|
|||
self.add_any_attr(aria_checked(value))
|
||||
}
|
||||
|
||||
/// Defines the number of columns in a table, grid, or treegrid.
|
||||
fn aria_colcount(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -53,6 +60,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -60,6 +68,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -67,6 +76,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -74,6 +84,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -81,6 +92,7 @@ where
|
|||
self.add_any_attr(aria_current(value))
|
||||
}
|
||||
|
||||
/// Identifies the element (or elements) that describes the object.
|
||||
fn aria_describedby(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -89,6 +101,7 @@ where
|
|||
self.add_any_attr(aria_describedby(value))
|
||||
}
|
||||
|
||||
/// Defines a string value that describes or annotates the current element.
|
||||
fn aria_description(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -97,6 +110,7 @@ where
|
|||
self.add_any_attr(aria_description(value))
|
||||
}
|
||||
|
||||
/// Identifies the element that provides additional information related to the object.
|
||||
fn aria_details(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -104,6 +118,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -111,6 +126,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -118,6 +134,7 @@ where
|
|||
self.add_any_attr(aria_dropeffect(value))
|
||||
}
|
||||
|
||||
/// Defines the element that provides an error message related to the object.
|
||||
fn aria_errormessage(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -126,6 +143,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -133,6 +151,7 @@ where
|
|||
self.add_any_attr(aria_expanded(value))
|
||||
}
|
||||
|
||||
/// Identifies the next element (or elements) in an alternate reading order of content.
|
||||
fn aria_flowto(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -140,6 +159,7 @@ where
|
|||
self.add_any_attr(aria_flowto(value))
|
||||
}
|
||||
|
||||
/// Indicates an element's "grabbed" state in a drag-and-drop operation.
|
||||
fn aria_grabbed(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -147,6 +167,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -154,6 +175,7 @@ where
|
|||
self.add_any_attr(aria_haspopup(value))
|
||||
}
|
||||
|
||||
/// Indicates whether the element is exposed to an accessibility API.
|
||||
fn aria_hidden(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -161,6 +183,7 @@ where
|
|||
self.add_any_attr(aria_hidden(value))
|
||||
}
|
||||
|
||||
/// Indicates the entered value does not conform to the format expected by the application.
|
||||
fn aria_invalid(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -168,6 +191,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -176,6 +200,7 @@ where
|
|||
self.add_any_attr(aria_keyshortcuts(value))
|
||||
}
|
||||
|
||||
/// Defines a string value that labels the current element.
|
||||
fn aria_label(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -183,6 +208,7 @@ where
|
|||
self.add_any_attr(aria_label(value))
|
||||
}
|
||||
|
||||
/// Identifies the element (or elements) that labels the current element.
|
||||
fn aria_labelledby(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -190,6 +216,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -197,6 +224,7 @@ where
|
|||
self.add_any_attr(aria_live(value))
|
||||
}
|
||||
|
||||
/// Indicates whether an element is modal when displayed.
|
||||
fn aria_modal(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -204,6 +232,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -211,6 +240,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -219,6 +249,7 @@ where
|
|||
self.add_any_attr(aria_multiselectable(value))
|
||||
}
|
||||
|
||||
/// Indicates whether the element's orientation is horizontal, vertical, or undefined.
|
||||
fn aria_orientation(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -227,6 +258,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -234,6 +266,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -242,6 +275,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -249,6 +283,7 @@ where
|
|||
self.add_any_attr(aria_posinset(value))
|
||||
}
|
||||
|
||||
/// Indicates the current "pressed" state of toggle buttons.
|
||||
fn aria_pressed(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -256,6 +291,7 @@ where
|
|||
self.add_any_attr(aria_pressed(value))
|
||||
}
|
||||
|
||||
/// Indicates that the element is not editable, but is otherwise operable.
|
||||
fn aria_readonly(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -263,6 +299,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -270,6 +307,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -277,6 +315,7 @@ where
|
|||
self.add_any_attr(aria_required(value))
|
||||
}
|
||||
|
||||
/// Defines a human-readable, author-localized description for the role of an element.
|
||||
fn aria_roledescription(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -285,6 +324,7 @@ where
|
|||
self.add_any_attr(aria_roledescription(value))
|
||||
}
|
||||
|
||||
/// Defines the total number of rows in a table, grid, or treegrid.
|
||||
fn aria_rowcount(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -292,6 +332,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -299,6 +340,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -306,6 +348,7 @@ where
|
|||
self.add_any_attr(aria_rowspan(value))
|
||||
}
|
||||
|
||||
/// Indicates the current "selected" state of various widgets.
|
||||
fn aria_selected(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -313,6 +356,7 @@ where
|
|||
self.add_any_attr(aria_selected(value))
|
||||
}
|
||||
|
||||
/// Defines the number of items in the current set of listitems or treeitems.
|
||||
fn aria_setsize(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -320,6 +364,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -327,6 +372,7 @@ where
|
|||
self.add_any_attr(aria_sort(value))
|
||||
}
|
||||
|
||||
/// Defines the maximum allowed value for a range widget.
|
||||
fn aria_valuemax(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -334,6 +380,7 @@ where
|
|||
self.add_any_attr(aria_valuemax(value))
|
||||
}
|
||||
|
||||
/// Defines the minimum allowed value for a range widget.
|
||||
fn aria_valuemin(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -341,6 +388,7 @@ where
|
|||
self.add_any_attr(aria_valuemin(value))
|
||||
}
|
||||
|
||||
/// Defines the current value for a range widget.
|
||||
fn aria_valuenow(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -348,6 +396,7 @@ where
|
|||
self.add_any_attr(aria_valuenow(value))
|
||||
}
|
||||
|
||||
/// Defines the human-readable text alternative of `aria-valuenow` for a range widget.
|
||||
fn aria_valuetext(
|
||||
self,
|
||||
value: V,
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
};
|
||||
use std::{borrow::Cow, marker::PhantomData, sync::Arc};
|
||||
|
||||
/// Adds a custom attribute with any key-value combintion.
|
||||
#[inline(always)]
|
||||
pub fn custom_attribute<K, V, R>(key: K, value: V) -> CustomAttr<K, V, R>
|
||||
where
|
||||
|
@ -20,6 +21,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A custom attribute with any key-value combination.
|
||||
#[derive(Debug)]
|
||||
pub struct CustomAttr<K, V, R>
|
||||
where
|
||||
|
@ -154,7 +156,9 @@ where
|
|||
}
|
||||
|
||||
// TODO this needs to be a method, not a const
|
||||
/// Defines a custom attribute key.
|
||||
pub trait CustomAttributeKey: Clone + AsRef<str> + Send + 'static {
|
||||
/// The attribute name.
|
||||
const KEY: &'static str;
|
||||
}
|
||||
|
||||
|
@ -181,6 +185,7 @@ impl<const K: &'static str> CustomAttributeKey
|
|||
const KEY: &'static str = K;
|
||||
}
|
||||
|
||||
/// Adds a custom attribute to an element.
|
||||
pub trait CustomAttribute<K, V, Rndr>
|
||||
where
|
||||
K: CustomAttributeKey,
|
||||
|
@ -188,6 +193,7 @@ where
|
|||
Rndr: DomRenderer,
|
||||
Self: Sized + AddAnyAttr<Rndr>,
|
||||
{
|
||||
/// Adds an HTML attribute by key and value.
|
||||
fn attr(
|
||||
self,
|
||||
key: K,
|
||||
|
|
|
@ -13,13 +13,16 @@ use crate::{
|
|||
};
|
||||
use core::convert::From;
|
||||
|
||||
/// Adds an attribute that modifies the `class`.
|
||||
pub trait ClassAttribute<C, Rndr>
|
||||
where
|
||||
C: IntoClass<Rndr>,
|
||||
Rndr: DomRenderer,
|
||||
{
|
||||
/// The type of the element with the new attribute added.
|
||||
type Output;
|
||||
|
||||
/// Adds a CSS class to an element.
|
||||
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>
|
||||
where
|
||||
P: IntoProperty<Rndr>,
|
||||
Rndr: DomRenderer,
|
||||
{
|
||||
/// The type of the element with the new attribute added.
|
||||
type Output;
|
||||
|
||||
/// Adds a DOM property to an element.
|
||||
fn prop(self, key: K, value: P) -> Self::Output;
|
||||
}
|
||||
|
||||
|
@ -54,18 +60,22 @@ where
|
|||
Rndr: DomRenderer,
|
||||
{
|
||||
type Output = <Self as AddAnyAttr<Rndr>>::Output<Property<K, P, Rndr>>;
|
||||
|
||||
fn prop(self, key: K, value: P) -> Self::Output {
|
||||
self.add_any_attr(prop(key, value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds an attribute that modifies the CSS styles.
|
||||
pub trait StyleAttribute<S, Rndr>
|
||||
where
|
||||
S: IntoStyle<Rndr>,
|
||||
Rndr: DomRenderer,
|
||||
{
|
||||
/// The type of the element with the new attribute added.
|
||||
type Output;
|
||||
|
||||
/// Adds a CSS style to an element.
|
||||
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> {
|
||||
/// The type of the element with the event listener added.
|
||||
type Output;
|
||||
|
||||
/// Adds an event listener to an element.
|
||||
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> {
|
||||
/// The type of the element with the new attribute added.
|
||||
type Output;
|
||||
|
||||
/// Adds an event listener with a typed target to an element definition.
|
||||
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>
|
||||
where
|
||||
Self: Sized + AddAnyAttr<Rndr>,
|
||||
V: AttributeValue<Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
/// The `accesskey` global attribute provides a hint for generating a keyboard shortcut for the current element.
|
||||
fn accesskey(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -143,6 +161,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -150,6 +169,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -157,6 +177,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -165,6 +186,7 @@ where
|
|||
self.add_any_attr(contenteditable(value))
|
||||
}
|
||||
|
||||
/// The `dir` global attribute is an enumerated attribute indicating the directionality of the element's text.
|
||||
fn dir(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -172,6 +194,7 @@ where
|
|||
self.add_any_attr(dir(value))
|
||||
}
|
||||
|
||||
/// The `draggable` global attribute is an enumerated attribute indicating whether the element can be dragged.
|
||||
fn draggable(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -179,6 +202,7 @@ where
|
|||
self.add_any_attr(draggable(value))
|
||||
}
|
||||
|
||||
/// The `enterkeyhint` global attribute is used to customize the enter key on virtual keyboards.
|
||||
fn enterkeyhint(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -186,6 +210,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -193,6 +218,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -200,6 +226,7 @@ where
|
|||
self.add_any_attr(id(value))
|
||||
}
|
||||
|
||||
/// The `inert` global attribute is a Boolean attribute that makes an element behave inertly.
|
||||
fn inert(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -207,6 +234,7 @@ where
|
|||
self.add_any_attr(inert(value))
|
||||
}
|
||||
|
||||
/// The `inputmode` global attribute provides a hint to browsers for which virtual keyboard to display.
|
||||
fn inputmode(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -214,6 +242,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -221,6 +250,7 @@ where
|
|||
self.add_any_attr(is(value))
|
||||
}
|
||||
|
||||
/// The `itemid` global attribute is used to specify the unique, global identifier of an item.
|
||||
fn itemid(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -228,6 +258,7 @@ where
|
|||
self.add_any_attr(itemid(value))
|
||||
}
|
||||
|
||||
/// The `itemprop` global attribute is used to add properties to an item.
|
||||
fn itemprop(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -235,6 +266,7 @@ where
|
|||
self.add_any_attr(itemprop(value))
|
||||
}
|
||||
|
||||
/// The `itemref` global attribute is used to refer to other elements.
|
||||
fn itemref(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -242,6 +274,7 @@ where
|
|||
self.add_any_attr(itemref(value))
|
||||
}
|
||||
|
||||
/// The `itemscope` global attribute is used to create a new item.
|
||||
fn itemscope(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -249,6 +282,7 @@ where
|
|||
self.add_any_attr(itemscope(value))
|
||||
}
|
||||
|
||||
/// The `itemtype` global attribute is used to specify the types of items.
|
||||
fn itemtype(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -256,6 +290,7 @@ where
|
|||
self.add_any_attr(itemtype(value))
|
||||
}
|
||||
|
||||
/// The `lang` global attribute helps define the language of an element.
|
||||
fn lang(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -263,6 +298,7 @@ where
|
|||
self.add_any_attr(lang(value))
|
||||
}
|
||||
|
||||
/// The `nonce` global attribute is used to specify a cryptographic nonce.
|
||||
fn nonce(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -270,6 +306,7 @@ where
|
|||
self.add_any_attr(nonce(value))
|
||||
}
|
||||
|
||||
/// The `part` global attribute identifies the element as a part of a component.
|
||||
fn part(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -277,6 +314,7 @@ where
|
|||
self.add_any_attr(part(value))
|
||||
}
|
||||
|
||||
/// The `popover` global attribute defines the popover's behavior.
|
||||
fn popover(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -284,6 +322,7 @@ where
|
|||
self.add_any_attr(popover(value))
|
||||
}
|
||||
|
||||
/// The `role` global attribute defines the role of an element in ARIA.
|
||||
fn role(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -291,6 +330,7 @@ where
|
|||
self.add_any_attr(role(value))
|
||||
}
|
||||
|
||||
/// The `slot` global attribute assigns a slot in a shadow DOM.
|
||||
fn slot(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -298,6 +338,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -305,6 +346,7 @@ where
|
|||
self.add_any_attr(spellcheck(value))
|
||||
}
|
||||
|
||||
/// The `tabindex` global attribute indicates if the element can take input focus.
|
||||
fn tabindex(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -312,6 +354,7 @@ where
|
|||
self.add_any_attr(tabindex(value))
|
||||
}
|
||||
|
||||
/// The `title` global attribute contains text representing advisory information.
|
||||
fn title(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -319,6 +362,7 @@ where
|
|||
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(
|
||||
self,
|
||||
value: V,
|
||||
|
@ -326,6 +370,7 @@ where
|
|||
self.add_any_attr(translate(value))
|
||||
}
|
||||
|
||||
/// The `virtualkeyboardpolicy` global attribute specifies the behavior of the virtual keyboard.
|
||||
fn virtualkeyboardpolicy(
|
||||
self,
|
||||
value: V,
|
||||
|
|
|
@ -2,14 +2,18 @@ use super::{Attr, AttributeValue};
|
|||
use crate::renderer::Renderer;
|
||||
use std::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
/// An HTML attribute key.
|
||||
pub trait AttributeKey: Clone + Send + 'static {
|
||||
/// The name of the attribute.
|
||||
const KEY: &'static str;
|
||||
}
|
||||
|
||||
macro_rules! attributes {
|
||||
($($key:ident $html:literal),* $(,)?) => {
|
||||
($(#[$meta:meta] $key:ident $html:literal),* $(,)?) => {
|
||||
paste::paste! {
|
||||
$(
|
||||
#[$meta]
|
||||
#[track_caller]
|
||||
pub fn $key<V, Rndr>(value: V) -> Attr<[<$key:camel>], V, Rndr>
|
||||
where V: AttributeValue<Rndr>,
|
||||
Rndr: Renderer
|
||||
|
@ -17,6 +21,7 @@ macro_rules! attributes {
|
|||
Attr([<$key:camel>], value, PhantomData)
|
||||
}
|
||||
|
||||
#[$meta]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct [<$key:camel>];
|
||||
|
||||
|
@ -28,311 +33,618 @@ macro_rules! attributes {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO attribute names with underscores should be kebab-cased
|
||||
attributes! {
|
||||
// HTML
|
||||
abbr "abbr", // [],
|
||||
accept_charset "accept-charset", // [],
|
||||
accept "accept", // [],
|
||||
accesskey "accesskey", // [], // [GlobalAttribute]
|
||||
action "action", // [],
|
||||
align "align", // [],
|
||||
allow "allow", // [],
|
||||
allowfullscreen "allowfullscreen", // [],
|
||||
allowpaymentrequest "allowpaymentrequest", // [],
|
||||
alt "alt", // [],
|
||||
/// The `abbr` attribute specifies an abbreviated form of the element's content.
|
||||
abbr "abbr",
|
||||
/// The `accept-charset` attribute specifies the character encodings that are to be used for the form submission.
|
||||
accept_charset "accept-charset",
|
||||
/// The `accept` attribute specifies a list of types the server accepts, typically a file type.
|
||||
accept "accept",
|
||||
/// The `accesskey` attribute specifies a shortcut key to activate or focus an element.
|
||||
accesskey "accesskey",
|
||||
/// The `action` attribute defines the URL to which the form data will be sent.
|
||||
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
|
||||
/// 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_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_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",
|
||||
/// The `aria-colcount` attribute defines the total number of columns in a table, grid, or treegrid.
|
||||
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",
|
||||
/// 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_controls "aria-controls", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_current "aria-current", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_describedby "aria-describedby", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_description "aria-description", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_details "aria-details", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_disabled "aria-disabled", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_dropeffect "aria-dropeffect", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_errormessage "aria-errormessage", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
/// The `aria-controls` attribute identifies the element (or elements) whose contents or presence are controlled by the current element.
|
||||
aria_controls "aria-controls",
|
||||
/// The `aria-current` attribute indicates the element representing the current item within a container or set of related elements.
|
||||
aria_current "aria-current",
|
||||
/// The `aria-describedby` attribute identifies the element (or elements) that describes the object.
|
||||
aria_describedby "aria-describedby",
|
||||
/// The `aria-description` attribute provides a string value that describes or annotates the current element.
|
||||
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_flowto "aria-flowto", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_grabbed "aria-grabbed", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_haspopup "aria-haspopup", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_hidden "aria-hidden", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_invalid "aria-invalid", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_keyshortcuts "aria-keyshortcuts", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_label "aria-label", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_labelledby "aria-labelledby", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
aria_live "aria-live", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
/// The `aria-flowto` attribute identifies the next element (or elements) in an alternate reading order of content.
|
||||
aria_flowto "aria-flowto",
|
||||
/// The `aria-grabbed` attribute indicates an element's "grabbed" state in a drag-and-drop operation.
|
||||
aria_grabbed "aria-grabbed",
|
||||
/// 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_haspopup "aria-haspopup",
|
||||
/// The `aria-hidden` attribute indicates whether the element is exposed to an accessibility API.
|
||||
aria_hidden "aria-hidden",
|
||||
/// 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",
|
||||
/// The `aria-multiline` attribute indicates whether a text box accepts multiple lines of input or only a single line.
|
||||
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",
|
||||
/// The `aria-orientation` attribute indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
|
||||
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",
|
||||
/// The `aria-posinset` attribute defines an element's position within a set or treegrid.
|
||||
aria_posinset "aria-posinset",
|
||||
/// The `aria-pressed` attribute indicates the current "pressed" state of toggle buttons.
|
||||
aria_pressed "aria-pressed",
|
||||
/// The `aria-readonly` attribute indicates that the element is not editable, but is otherwise operable.
|
||||
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_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",
|
||||
/// 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",
|
||||
/// 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",
|
||||
/// The `aria-selected` attribute indicates the current "selected" state of various widgets.
|
||||
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",
|
||||
/// The `aria-sort` attribute indicates if items in a table or grid are sorted in ascending or descending order.
|
||||
aria_sort "aria-sort",
|
||||
/// The `aria-valuemax` attribute defines the maximum allowed value for a range widget.
|
||||
aria_valuemax "aria-valuemax",
|
||||
/// The `aria-valuemin` attribute defines the minimum allowed value for a range widget.
|
||||
aria_valuemin "aria-valuemin",
|
||||
/// The `aria-valuenow` attribute defines the current value for a range widget.
|
||||
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",
|
||||
r#as "as", // [],
|
||||
r#async "async", // [],
|
||||
autocapitalize "autocapitalize", // [], // [GlobalAttribute]
|
||||
autocomplete "autocomplete", // [],
|
||||
autofocus "autofocus", // [], // [GlobalAttribute]
|
||||
autoplay "autoplay", // [],
|
||||
background "background", // [],
|
||||
bgcolor "bgcolor", // [],
|
||||
blocking "blocking", // [],
|
||||
border "border", // [],
|
||||
buffered "buffered", // [],
|
||||
capture "capture", // [],
|
||||
challenge "challenge", // [],
|
||||
charset "charset", // [],
|
||||
checked "checked", // [],
|
||||
cite "cite", // [],
|
||||
/// The `as` attribute specifies the type of destination for the content of the link.
|
||||
r#as "as",
|
||||
/// The `async` attribute indicates that the script should be executed asynchronously.
|
||||
r#async "async",
|
||||
/// The `autocapitalize` attribute controls whether and how text input is automatically capitalized as it is entered/edited by the user.
|
||||
autocapitalize "autocapitalize",
|
||||
/// The `autocomplete` attribute indicates whether an input field can have its value automatically completed by the browser.
|
||||
autocomplete "autocomplete",
|
||||
/// The `autofocus` attribute indicates that an element should be focused on page load.
|
||||
autofocus "autofocus",
|
||||
/// The `autoplay` attribute indicates that the media should start playing as soon as it is loaded.
|
||||
autoplay "autoplay",
|
||||
/// The `background` attribute sets the URL of the background image for the document.
|
||||
background "background",
|
||||
/// The `bgcolor` attribute sets the background color of an element.
|
||||
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 "class", // [],
|
||||
code "code", // [],
|
||||
color "color", // [],
|
||||
cols "cols", // [],
|
||||
colspan "colspan", // [],
|
||||
content "content", // [],
|
||||
contenteditable "contenteditable", // [], // [GlobalAttribute]
|
||||
contextmenu "contextmenu", // [], // [GlobalAttribute]
|
||||
controls "controls", // [],
|
||||
controlslist "controlslist", // [],
|
||||
coords "coords", // [],
|
||||
crossorigin "crossorigin", // [],
|
||||
csp "csp", // [],
|
||||
data "data", // [],
|
||||
datetime "datetime", // [],
|
||||
decoding "decoding", // [],
|
||||
default "default", // [],
|
||||
defer "defer", // [],
|
||||
dir "dir", // [], // [GlobalAttribute]
|
||||
dirname "dirname", // [],
|
||||
disabled "disabled", // [],
|
||||
disablepictureinpicture "disablepictureinpicture", // [],
|
||||
disableremoteplayback "disableremoteplayback", // [],
|
||||
download "download", // [],
|
||||
draggable "draggable", // [], // [GlobalAttribute]
|
||||
enctype "enctype", // [],
|
||||
enterkeyhint "enterkeyhint", // [], // [GlobalAttribute]
|
||||
exportparts "exportparts", // [], // [GlobalAttribute]
|
||||
fetchpriority "fetchprioty", // [],
|
||||
r#for "for", // [],
|
||||
form "form", // [],
|
||||
formaction "formaction", // [],
|
||||
formenctype "formenctype", // [],
|
||||
formmethod "formmethod", // [],
|
||||
formnovalidate "formnovalidate", // [],
|
||||
formtarget "formtarget", // [],
|
||||
headers "headers", // [],
|
||||
height "height", // [],
|
||||
hidden "hidden", // [], // [GlobalAttribute]
|
||||
high "high", // [],
|
||||
href "href", // [],
|
||||
hreflang "hreflang", // [],
|
||||
http_equiv "http-equiv", // [],
|
||||
icon "icon", // [],
|
||||
id "id", // [], // [GlobalAttribute]
|
||||
//class "class",
|
||||
/// The `code` attribute specifies the URL of the applet's class file to be loaded and executed.
|
||||
code "code",
|
||||
/// The `color` attribute specifies the color of an element's text.
|
||||
color "color",
|
||||
/// The `cols` attribute specifies the visible width of a text area.
|
||||
cols "cols",
|
||||
/// The `colspan` attribute defines the number of columns a cell should span.
|
||||
colspan "colspan",
|
||||
/// The `content` attribute gives the value associated with the http-equiv or name attribute.
|
||||
content "content",
|
||||
/// The `contenteditable` attribute indicates whether the element's content is editable.
|
||||
contenteditable "contenteditable",
|
||||
/// The `contextmenu` attribute specifies the ID of a `<menu>` element to open as a context menu.
|
||||
contextmenu "contextmenu",
|
||||
/// The `controls` attribute indicates whether the browser should display playback controls for the media.
|
||||
controls "controls",
|
||||
/// The `controlslist` attribute allows the control of which controls to show on the media element whenever the browser shows its native controls.
|
||||
controlslist "controlslist",
|
||||
/// The `coords` attribute specifies the coordinates of an area in an image map.
|
||||
coords "coords",
|
||||
/// The `crossorigin` attribute indicates whether the resource should be fetched with a CORS request.
|
||||
crossorigin "crossorigin",
|
||||
/// The `csp` attribute allows the embedding document to define the Content Security Policy that an embedded document must agree to enforce upon itself.
|
||||
csp "csp",
|
||||
/// The `data` attribute specifies the URL of the resource that is being embedded.
|
||||
data "data",
|
||||
/// The `datetime` attribute specifies the date and time.
|
||||
datetime "datetime",
|
||||
/// The `decoding` attribute indicates the preferred method for decoding images.
|
||||
decoding "decoding",
|
||||
/// The `default` attribute indicates that the track should be enabled unless the user's preferences indicate that another track is more appropriate.
|
||||
default "default",
|
||||
/// The `defer` attribute indicates that the script should be executed after the document has been parsed.
|
||||
defer "defer",
|
||||
/// The `dir` attribute specifies the text direction for the content in an element.
|
||||
dir "dir",
|
||||
/// The `dirname` attribute identifies the text directionality of an input element.
|
||||
dirname "dirname",
|
||||
/// The `disabled` attribute indicates whether the element is disabled.
|
||||
disabled "disabled",
|
||||
/// The `disablepictureinpicture` attribute indicates that the element is not allowed to be displayed in Picture-in-Picture mode.
|
||||
disablepictureinpicture "disablepictureinpicture",
|
||||
/// The `disableremoteplayback` attribute indicates that the element is not allowed to be displayed using remote playback.
|
||||
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",
|
||||
/// The `imagesrcset` attribute specifies the URLs of multiple images to be used in different situations.
|
||||
imagesrcset "imagesrcset",
|
||||
importance "importance", // [],
|
||||
inert "inert", // [], // [GlobalAttribute]
|
||||
inputmode "inputmode", // [], // [GlobalAttribute]
|
||||
integrity "integrity", // [],
|
||||
intrinsicsize "intrinsicsize", // [],
|
||||
is "is", // [], // [GlobalAttribute]
|
||||
ismap "ismap", // [],
|
||||
itemid "itemid", // [], // [GlobalAttribute]
|
||||
itemprop "itemprop", // [], // [GlobalAttribute]
|
||||
itemref "itemref", // [], // [GlobalAttribute]
|
||||
itemscope "itemscope", // [], // [GlobalAttribute]
|
||||
itemtype "itemtype", // [], // [GlobalAttribute]
|
||||
keytype "keytype", // [],
|
||||
kind "kind", // [],
|
||||
label "label", // [],
|
||||
lang "lang", // [], // [GlobalAttribute]
|
||||
language "language", // [],
|
||||
list "list", // [],
|
||||
loading "loading", // [],
|
||||
r#loop "loop", // [],
|
||||
low "low", // [],
|
||||
manifest "manifest", // [],
|
||||
max "max", // [],
|
||||
maxlength "maxlength", // [],
|
||||
media "media", // [],
|
||||
method "method", // [],
|
||||
min "min", // [],
|
||||
minlength "minlength", // [],
|
||||
multiple "multiple", // [],
|
||||
muted "muted", // [],
|
||||
name "name", // [],
|
||||
nomodule "nomodule", // [],
|
||||
nonce "nonce", // [], // [GlobalAttribute]
|
||||
novalidate "novalidate", // [],
|
||||
open "open", // [],
|
||||
optimum "optimum", // [],
|
||||
part "part", // [], // [GlobalAttribute]
|
||||
pattern "pattern", // [],
|
||||
ping "ping", // [],
|
||||
placeholder "placeholder", // [],
|
||||
playsinline "playsinline", // [],
|
||||
popover "popover", // [], // [GlobalAttribute]
|
||||
/// The `importance` attribute specifies the relative importance of the element.
|
||||
importance "importance",
|
||||
/// The `inert` attribute indicates that the element is non-interactive and won't be accessible to user interactions or assistive technologies.
|
||||
inert "inert",
|
||||
/// The `inputmode` attribute specifies the type of data that the user will enter.
|
||||
inputmode "inputmode",
|
||||
/// The `integrity` attribute contains a hash value that the browser can use to verify that the resource hasn't been altered.
|
||||
integrity "integrity",
|
||||
/// The `intrinsicsize` attribute specifies the intrinsic size of an image or video.
|
||||
intrinsicsize "intrinsicsize",
|
||||
/// The `is` attribute allows you to specify the name of a custom element.
|
||||
is "is",
|
||||
/// The `ismap` attribute indicates that the image is part of a server-side image map.
|
||||
ismap "ismap",
|
||||
/// The `itemid` attribute assigns a unique identifier to an item.
|
||||
itemid "itemid",
|
||||
/// The `itemprop` attribute adds a property to an item.
|
||||
itemprop "itemprop",
|
||||
/// The `itemref` attribute provides a list of element IDs that have additional properties for the item.
|
||||
itemref "itemref",
|
||||
/// The `itemscope` attribute creates a new item and adds it to the page's items.
|
||||
itemscope "itemscope",
|
||||
/// The `itemtype` attribute specifies the type of an item.
|
||||
itemtype "itemtype",
|
||||
/// The `keytype` attribute specifies the type of key used by the `<keygen>` element.
|
||||
keytype "keytype",
|
||||
/// The `kind` attribute specifies the kind of text track.
|
||||
kind "kind",
|
||||
/// The `label` attribute provides a user-readable title for an element.
|
||||
label "label",
|
||||
/// The `lang` attribute specifies the language of the element's content.
|
||||
lang "lang",
|
||||
/// The `language` attribute specifies the scripting language used for the script.
|
||||
language "language",
|
||||
/// The `list` attribute identifies a `<datalist>` element that contains pre-defined options for an `<input>` element.
|
||||
list "list",
|
||||
/// The `loading` attribute indicates how the browser should load the image.
|
||||
loading "loading",
|
||||
/// The `loop` attribute indicates whether the media should start over again when it reaches the end.
|
||||
r#loop "loop",
|
||||
/// The `low` attribute specifies the range that is considered to be a low value.
|
||||
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",
|
||||
/// The `popovertargetaction` attribute specifies the action that shows the popover.
|
||||
popovertargetaction "popovertargetaction",
|
||||
poster "poster", // [],
|
||||
preload "preload", // [],
|
||||
radiogroup "radiogroup", // [],
|
||||
readonly "readonly", // [],
|
||||
referrerpolicy "referrerpolicy", // [],
|
||||
rel "rel", // [],
|
||||
required "required", // [],
|
||||
reversed "reversed", // [],
|
||||
role "role", // [], // [GlobalAttribute] // [AriaAttribute],
|
||||
rows "rows", // [],
|
||||
rowspan "rowspan", // [],
|
||||
sandbox "sandbox", // [],
|
||||
scope "scope", // [],
|
||||
scoped "scoped", // [],
|
||||
selected "selected", // [],
|
||||
shape "shape", // [],
|
||||
size "size", // [],
|
||||
sizes "sizes", // [],
|
||||
slot "slot", // [], // [GlobalAttribute]
|
||||
span "span", // [],
|
||||
spellcheck "spellcheck", // [], // [GlobalAttribute]
|
||||
src "src", // [],
|
||||
srcdoc "srcdoc", // [],
|
||||
srclang "srclang", // [],
|
||||
srcset "srcset", // [],
|
||||
start "start", // [],
|
||||
step "step", // [],
|
||||
/// The `poster` attribute specifies an image to be shown while the video is downloading or until the user hits the play button.
|
||||
poster "poster",
|
||||
/// The `preload` attribute specifies if and how the author thinks that the media file should be loaded when the page loads.
|
||||
preload "preload",
|
||||
/// The `radiogroup` attribute specifies the name of the group to which the element belongs.
|
||||
radiogroup "radiogroup",
|
||||
/// The `readonly` attribute indicates that the user cannot modify the value of the input element.
|
||||
readonly "readonly",
|
||||
/// The `referrerpolicy` attribute specifies which referrer information to include with requests.
|
||||
referrerpolicy "referrerpolicy",
|
||||
/// The `rel` attribute specifies the relationship between the current document and the linked document.
|
||||
rel "rel",
|
||||
/// The `required` attribute indicates that the user must fill in the input element before submitting the form.
|
||||
required "required",
|
||||
/// The `reversed` attribute indicates that the list should be displayed in a descending order.
|
||||
reversed "reversed",
|
||||
/// The `role` attribute defines the role of an element in the context of a web application.
|
||||
role "role",
|
||||
/// The `rows` attribute specifies the number of visible text lines for a text area.
|
||||
rows "rows",
|
||||
/// The `rowspan` attribute defines the number of rows a cell should span.
|
||||
rowspan "rowspan",
|
||||
/// The `sandbox` attribute applies extra restrictions to the content in the `<iframe>`.
|
||||
sandbox "sandbox",
|
||||
/// The `scope` attribute specifies whether a header cell is a header for a column, row, or group of columns or rows.
|
||||
scope "scope",
|
||||
/// 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 "style", // [],
|
||||
summary "summary", // [],
|
||||
tabindex "tabindex", // [], // [GlobalAttribute]
|
||||
target "target", // [],
|
||||
title "title", // [], // [GlobalAttribute]
|
||||
translate "translate", // [], // [GlobalAttribute]
|
||||
r#type "type", // [],
|
||||
usemap "usemap", // [],
|
||||
value "value", // [],
|
||||
virtualkeyboardpolicy "virtualkeyboardpolicy", // [], // [GlobalAttribute]
|
||||
width "width", // [],
|
||||
wrap "wrap", // [],
|
||||
// style "style",
|
||||
/// The `summary` attribute provides a summary of the content of the table.
|
||||
summary "summary",
|
||||
/// The `tabindex` attribute specifies the tab order of an element.
|
||||
tabindex "tabindex",
|
||||
/// The `target` attribute specifies where to open the linked document.
|
||||
target "target",
|
||||
/// The `title` attribute provides additional information about an element.
|
||||
title "title",
|
||||
/// The `translate` attribute specifies whether the content of an element should be translated or not.
|
||||
translate "translate",
|
||||
/// 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
|
||||
onabort "onabort", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onautocomplete "onautocomplete", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onautocompleteerror "onautocompleteerror", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onblur "onblur", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
oncancel "oncancel", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
oncanplay "oncanplay", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
oncanplaythrough "oncanplaythrough", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onchange "onchange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onclick "onclick", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onclose "onclose", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
oncontextmenu "oncontextmenu", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
oncuechange "oncuechange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondblclick "ondblclick", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondrag "ondrag", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondragend "ondragend", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondragenter "ondragenter", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondragleave "ondragleave", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondragover "ondragover", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondragstart "ondragstart", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondrop "ondrop", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ondurationchange "ondurationchange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onemptied "onemptied", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onended "onended", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onerror "onerror", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onfocus "onfocus", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
oninput "oninput", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
oninvalid "oninvalid", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onkeydown "onkeydown", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onkeypress "onkeypress", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onkeyup "onkeyup", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onload "onload", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onloadeddata "onloadeddata", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onloadedmetadata "onloadedmetadata", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onloadstart "onloadstart", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmousedown "onmousedown", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmouseenter "onmouseenter", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmouseleave "onmouseleave", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmousemove "onmousemove", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmouseout "onmouseout", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmouseover "onmouseover", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmouseup "onmouseup", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onmousewheel "onmousewheel", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onpause "onpause", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onplay "onplay", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onplaying "onplaying", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onprogress "onprogress", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onratechange "onratechange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onreset "onreset", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onresize "onresize", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onscroll "onscroll", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onseeked "onseeked", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onseeking "onseeking", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onselect "onselect", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onshow "onshow", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onsort "onsort", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onstalled "onstalled", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onsubmit "onsubmit", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onsuspend "onsuspend", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ontimeupdate "ontimeupdate", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
ontoggle "ontoggle", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onvolumechange "onvolumechange", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
onwaiting "onwaiting", // [], // [GlobalAttribute] // [EventHandlerAttribute],
|
||||
/// The `onabort` attribute specifies the event handler for the abort event.
|
||||
onabort "onabort",
|
||||
/// The `onautocomplete` attribute specifies the event handler for the autocomplete event.
|
||||
onautocomplete "onautocomplete",
|
||||
/// The `onautocompleteerror` attribute specifies the event handler for the autocompleteerror event.
|
||||
onautocompleteerror "onautocompleteerror",
|
||||
/// The `onblur` attribute specifies the event handler for the blur event.
|
||||
onblur "onblur",
|
||||
/// The `oncancel` attribute specifies the event handler for the cancel event.
|
||||
oncancel "oncancel",
|
||||
/// The `oncanplay` attribute specifies the event handler for the canplay event.
|
||||
oncanplay "oncanplay",
|
||||
/// The `oncanplaythrough` attribute specifies the event handler for the canplaythrough event.
|
||||
oncanplaythrough "oncanplaythrough",
|
||||
/// The `onchange` attribute specifies the event handler for the change event.
|
||||
onchange "onchange",
|
||||
/// The `onclick` attribute specifies the event handler for the click event.
|
||||
onclick "onclick",
|
||||
/// The `onclose` attribute specifies the event handler for the close event.
|
||||
onclose "onclose",
|
||||
/// The `oncontextmenu` attribute specifies the event handler for the contextmenu event.
|
||||
oncontextmenu "oncontextmenu",
|
||||
/// The `oncuechange` attribute specifies the event handler for the cuechange event.
|
||||
oncuechange "oncuechange",
|
||||
/// The `ondblclick` attribute specifies the event handler for the double click event.
|
||||
ondblclick "ondblclick",
|
||||
/// The `ondrag` attribute specifies the event handler for the drag event.
|
||||
ondrag "ondrag",
|
||||
/// The `ondragend` attribute specifies the event handler for the dragend event.
|
||||
ondragend "ondragend",
|
||||
/// The `ondragenter` attribute specifies the event handler for the dragenter event.
|
||||
ondragenter "ondragenter",
|
||||
/// The `ondragleave` attribute specifies the event handler for the dragleave event.
|
||||
ondragleave "ondragleave",
|
||||
/// The `ondragover` attribute specifies the event handler for the dragover event.
|
||||
ondragover "ondragover",
|
||||
/// The `ondragstart` attribute specifies the event handler for the dragstart event.
|
||||
ondragstart "ondragstart",
|
||||
/// The `ondrop` attribute specifies the event handler for the drop event.
|
||||
ondrop "ondrop",
|
||||
/// The `ondurationchange` attribute specifies the event handler for the durationchange event.
|
||||
ondurationchange "ondurationchange",
|
||||
/// The `onemptied` attribute specifies the event handler for the emptied event.
|
||||
onemptied "onemptied",
|
||||
/// The `onended` attribute specifies the event handler for the ended event.
|
||||
onended "onended",
|
||||
/// The `onerror` attribute specifies the event handler for the error event.
|
||||
onerror "onerror",
|
||||
/// The `onfocus` attribute specifies the event handler for the focus event.
|
||||
onfocus "onfocus",
|
||||
/// The `onformdata` attribute specifies the event handler for the formdata event.
|
||||
onformdata "onformdata",
|
||||
/// The `oninput` attribute specifies the event handler for the input event.
|
||||
oninput "oninput",
|
||||
/// The `oninvalid` attribute specifies the event handler for the invalid event.
|
||||
oninvalid "oninvalid",
|
||||
/// The `onkeydown` attribute specifies the event handler for the keydown event.
|
||||
onkeydown "onkeydown",
|
||||
/// The `onkeypress` attribute specifies the event handler for the keypress event.
|
||||
onkeypress "onkeypress",
|
||||
/// The `onkeyup` attribute specifies the event handler for the keyup event.
|
||||
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",
|
||||
/// The `accentunder` attribute specifies whether the element should be treated as an accent under the base element.
|
||||
accentunder "accentunder",
|
||||
/// The `columnalign` attribute specifies the alignment of columns.
|
||||
columnalign "columnalign",
|
||||
/// The `columnlines` attribute specifies the presence of lines between columns.
|
||||
columnlines "columnlines",
|
||||
/// The `columnspacing` attribute specifies the spacing between columns.
|
||||
columnspacing "columnspacing",
|
||||
/// The `columnspan` attribute specifies the number of columns the element should span.
|
||||
columnspan "columnspan",
|
||||
/// The `depth` attribute specifies the depth of the element.
|
||||
depth "depth",
|
||||
/// The `display` attribute specifies the display style of the element.
|
||||
display "display",
|
||||
/// The `displaystyle` attribute specifies whether the element is displayed in display style.
|
||||
displaystyle "displaystyle",
|
||||
/// The `fence` attribute specifies whether the element should act as a fence.
|
||||
fence "fence",
|
||||
/// The `frame` attribute specifies the type of frame for the element.
|
||||
frame "frame",
|
||||
/// The `framespacing` attribute specifies the spacing around frames.
|
||||
framespacing "framespacing",
|
||||
/// The `linethickness` attribute specifies the thickness of lines.
|
||||
linethickness "linethickness",
|
||||
/// The `lspace` attribute specifies the space on the left side of the element.
|
||||
lspace "lspace",
|
||||
/// The `mathbackground` attribute specifies the background color of the element.
|
||||
mathbackground "mathbackground",
|
||||
/// The `mathcolor` attribute specifies the color of the element.
|
||||
mathcolor "mathcolor",
|
||||
/// The `mathsize` attribute specifies the size of the element.
|
||||
mathsize "mathsize",
|
||||
/// The `mathvariant` attribute specifies the mathematical variant of the element.
|
||||
mathvariant "mathvariant",
|
||||
/// The `maxsize` attribute specifies the maximum size of the element.
|
||||
maxsize "maxsize",
|
||||
/// The `minsize` attribute specifies the minimum size of the element.
|
||||
minsize "minsize",
|
||||
/// The `movablelimits` attribute specifies whether the limits of the element are movable.
|
||||
movablelimits "movablelimits",
|
||||
/// The `notation` attribute specifies the type of notation for the element.
|
||||
notation "notation",
|
||||
/// The `rowalign` attribute specifies the alignment of rows.
|
||||
rowalign "rowalign",
|
||||
/// The `rowlines` attribute specifies the presence of lines between rows.
|
||||
rowlines "rowlines",
|
||||
/// The `rowspacing` attribute specifies the spacing between rows.
|
||||
rowspacing "rowspacing",
|
||||
/// The `rspace` attribute specifies the space on the right side of the element.
|
||||
rspace "rspace",
|
||||
/// The `scriptlevel` attribute specifies the script level of the element.
|
||||
scriptlevel "scriptlevel",
|
||||
/// The `separator` attribute specifies whether the element is a separator.
|
||||
separator "separator",
|
||||
/// The `stretchy` attribute specifies whether the element is stretchy.
|
||||
stretchy "stretchy",
|
||||
/// The `symmetric` attribute specifies whether the element is symmetric.
|
||||
symmetric "symmetric",
|
||||
/// The `voffset` attribute specifies the vertical offset of the element.
|
||||
voffset "voffset",
|
||||
/// The `xmlns` attribute specifies the XML namespace of the element.
|
||||
xmlns "xmlns",
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/// A type-erased `AnyAttribute`.
|
||||
pub mod any_attribute;
|
||||
/// Types for ARIA attributes.
|
||||
pub mod aria;
|
||||
/// Types for custom attributes.
|
||||
pub mod custom;
|
||||
/// Traits to define global attribute methods on all HTML elements.
|
||||
pub mod global;
|
||||
mod key;
|
||||
mod value;
|
||||
|
@ -12,16 +16,29 @@ pub use key::*;
|
|||
use std::{fmt::Debug, future::Future, marker::PhantomData};
|
||||
pub use value::*;
|
||||
|
||||
/// Defines an attribute: anything that can modify an element.
|
||||
pub trait Attribute<R: Renderer>: NextAttribute<R> + Send {
|
||||
/// The minimum length of this attribute in HTML.
|
||||
const MIN_LENGTH: usize;
|
||||
|
||||
/// The state that should be retained between building and rebuilding.
|
||||
type State;
|
||||
/// The type once all async data have loaded.
|
||||
type AsyncOutput: Attribute<R>;
|
||||
/// An equivalent to this attribute that can be cloned to be shared across elements.
|
||||
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;
|
||||
|
||||
/// An approximation of the actual length of this attribute in HTML.
|
||||
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(
|
||||
self,
|
||||
buf: &mut String,
|
||||
|
@ -30,24 +47,39 @@ pub trait Attribute<R: Renderer>: NextAttribute<R> + Send {
|
|||
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;
|
||||
|
||||
/// Adds this attribute to the element during client-side rendering.
|
||||
fn build(self, el: &R::Element) -> Self::State;
|
||||
|
||||
/// Applies a new value for the attribute.
|
||||
fn rebuild(self, state: &mut Self::State);
|
||||
|
||||
/// Converts this attribute into an equivalent that can be cloned.
|
||||
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;
|
||||
|
||||
/// “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);
|
||||
|
||||
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||
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> {
|
||||
/// The type of the new, combined attribute.
|
||||
type Output<NewAttr: Attribute<R>>: Attribute<R>;
|
||||
|
||||
/// Adds a new attribute.
|
||||
fn add_any_attr<NewAttr: Attribute<R>>(
|
||||
self,
|
||||
new_attr: NewAttr,
|
||||
|
@ -112,6 +144,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// An attribute with a key and value.
|
||||
#[derive(Debug)]
|
||||
pub struct Attr<K, V, R>(pub K, pub V, pub PhantomData<R>)
|
||||
where
|
||||
|
|
|
@ -11,8 +11,12 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
|
||||
/// A possible value for an HTML attribute.
|
||||
pub trait AttributeValue<R: Renderer>: Send {
|
||||
/// The state that should be retained between building and rebuilding.
|
||||
type State;
|
||||
|
||||
/// The type once all async data have loaded.
|
||||
type AsyncOutput: AttributeValue<R>;
|
||||
|
||||
/// 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.
|
||||
type CloneableOwned: AttributeValue<R> + Clone + 'static;
|
||||
|
||||
/// An approximation of the actual length of this attribute in HTML.
|
||||
fn html_len(&self) -> usize;
|
||||
|
||||
/// Renders the attribute value to HTML.
|
||||
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);
|
||||
|
||||
/// 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,
|
||||
key: &str,
|
||||
el: &R::Element,
|
||||
) -> Self::State;
|
||||
|
||||
/// Adds this attribute to the element during client-side rendering.
|
||||
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);
|
||||
|
||||
/// Converts this attribute into an equivalent that can be cloned.
|
||||
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;
|
||||
|
||||
/// “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);
|
||||
|
||||
/// “Resolves” this into a form that is not waiting for any asynchronous data.
|
||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
|||
};
|
||||
use std::{future::Future, marker::PhantomData, sync::Arc};
|
||||
|
||||
/// Adds a CSS class.
|
||||
#[inline(always)]
|
||||
pub fn class<C, R>(class: C) -> Class<C, R>
|
||||
where
|
||||
|
@ -17,6 +18,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A CSS class.
|
||||
#[derive(Debug)]
|
||||
pub struct Class<C, R> {
|
||||
class: C,
|
||||
|
@ -133,34 +135,54 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A possible value for a CSS class.
|
||||
pub trait IntoClass<R: DomRenderer>: Send {
|
||||
/// The HTML that should be included in a `<template>`.
|
||||
const TEMPLATE: &'static str = "";
|
||||
/// The minimum length of the HTML.
|
||||
const MIN_LENGTH: usize = Self::TEMPLATE.len();
|
||||
|
||||
/// The type after all async data have resolved.
|
||||
type AsyncOutput: IntoClass<R>;
|
||||
/// The view state retained between building and rebuilding.
|
||||
type State;
|
||||
/// An equivalent value that can be cloned.
|
||||
type Cloneable: IntoClass<R> + Clone;
|
||||
/// An equivalent value that can be cloned and is `'static`.
|
||||
type CloneableOwned: IntoClass<R> + Clone + 'static;
|
||||
|
||||
/// The estimated length of the HTML.
|
||||
fn html_len(&self) -> usize;
|
||||
|
||||
/// Renders the class to HTML.
|
||||
fn to_html(self, class: &mut String);
|
||||
|
||||
/// Renders the class to HTML for a `<template>`.
|
||||
#[allow(unused)] // it's used with `nightly` feature
|
||||
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;
|
||||
|
||||
/// Adds this class to the element during client-side rendering.
|
||||
fn build(self, el: &R::Element) -> Self::State;
|
||||
|
||||
/// Updates the value.
|
||||
fn rebuild(self, state: &mut Self::State);
|
||||
|
||||
/// Converts this to a cloneable type.
|
||||
fn into_cloneable(self) -> Self::Cloneable;
|
||||
|
||||
/// Converts this to a cloneable, owned type.
|
||||
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);
|
||||
|
||||
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,18 @@ use crate::{
|
|||
use send_wrapper::SendWrapper;
|
||||
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>
|
||||
where
|
||||
D: IntoDirective<T, P, Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
/// The type of the element with the directive added.
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
pub fn directive<T, P, D, R>(handler: D, param: P) -> Directive<T, D, P, R>
|
||||
where
|
||||
|
@ -46,6 +53,7 @@ where
|
|||
}))
|
||||
}
|
||||
|
||||
/// Custom logic that runs in the browser when the element is created or hydrated.
|
||||
#[derive(Debug)]
|
||||
pub struct Directive<T, D, P, R>(SendWrapper<DirectiveInner<T, D, P, R>>);
|
||||
|
||||
|
@ -60,7 +68,7 @@ where
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirectiveInner<T, D, P, R> {
|
||||
struct DirectiveInner<T, D, P, R> {
|
||||
handler: D,
|
||||
param: P,
|
||||
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
|
||||
/// second is the parameter that is provided in the attribute.
|
||||
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;
|
||||
|
||||
/// Calls the handler function
|
||||
fn run(&self, el: R::Element, param: P);
|
||||
|
||||
/// Converts this into a cloneable type.
|
||||
fn into_cloneable(self) -> Self::Cloneable;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
use std::{borrow::Cow, fmt::Debug, marker::PhantomData, sync::Arc};
|
||||
|
||||
// FIXME custom element HTML rendering is broken because tag names aren't static
|
||||
/// Creates a custom element.
|
||||
#[track_caller]
|
||||
pub fn custom<E, Rndr>(tag: E) -> HtmlElement<Custom<E>, (), (), Rndr>
|
||||
where
|
||||
|
@ -22,6 +23,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A custom HTML element.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Custom<E>(E)
|
||||
where
|
||||
|
@ -57,8 +59,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// The element name for a custom element.
|
||||
// TODO these are all broken for custom elements
|
||||
pub trait CustomElementKey: AsRef<str> + Send {
|
||||
/// The element name.
|
||||
const KEY: &'static str;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,18 +27,22 @@ use web_sys::Element;
|
|||
/// let remove = element.on(ev::blur, move |_| /* ... */);
|
||||
/// ```
|
||||
pub trait ElementExt {
|
||||
/// Adds an attribute to the element, at runtime.
|
||||
fn attr<At>(&self, attribute: At) -> At::State
|
||||
where
|
||||
At: Attribute<Dom>;
|
||||
|
||||
/// Adds a class to the element, at runtime.
|
||||
fn class<C>(&self, class: C) -> C::State
|
||||
where
|
||||
C: IntoClass<Dom>;
|
||||
|
||||
/// Adds a style to the element, at runtime.
|
||||
fn style<S>(&self, style: S) -> S::State
|
||||
where
|
||||
S: IntoStyle<Dom>;
|
||||
|
||||
/// Adds an event listener to the element, at runtime.
|
||||
fn on<E>(
|
||||
&self,
|
||||
ev: E,
|
||||
|
|
|
@ -6,6 +6,14 @@ use crate::{
|
|||
};
|
||||
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)]
|
||||
pub fn inner_html<T, R>(value: T) -> InnerHtml<T, R>
|
||||
where
|
||||
|
@ -18,6 +26,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the inner HTML of an element.
|
||||
#[derive(Debug)]
|
||||
pub struct InnerHtml<T, R> {
|
||||
value: T,
|
||||
|
@ -118,12 +127,21 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the inner HTML of an element.
|
||||
pub trait InnerHtmlAttribute<T, Rndr>
|
||||
where
|
||||
T: InnerHtmlValue<Rndr>,
|
||||
Rndr: DomRenderer,
|
||||
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(
|
||||
self,
|
||||
value: T,
|
||||
|
@ -149,30 +167,48 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A possible value for [`InnerHtml`].
|
||||
pub trait InnerHtmlValue<R: DomRenderer>: Send {
|
||||
/// The type after all async data have resolved.
|
||||
type AsyncOutput: InnerHtmlValue<R>;
|
||||
/// The view state retained between building and rebuilding.
|
||||
type State;
|
||||
/// An equivalent value that can be cloned.
|
||||
type Cloneable: InnerHtmlValue<R> + Clone;
|
||||
/// An equivalent value that can be cloned and is `'static`.
|
||||
type CloneableOwned: InnerHtmlValue<R> + Clone + 'static;
|
||||
|
||||
/// The estimated length of the HTML.
|
||||
fn html_len(&self) -> usize;
|
||||
|
||||
/// Renders the class to HTML.
|
||||
fn to_html(self, buf: &mut String);
|
||||
|
||||
/// Renders the class to HTML for a `<template>`.
|
||||
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;
|
||||
|
||||
/// Adds this class to the element during client-side rendering.
|
||||
fn build(self, el: &R::Element) -> Self::State;
|
||||
|
||||
/// Updates the value.
|
||||
fn rebuild(self, state: &mut Self::State);
|
||||
|
||||
/// Converts this to a cloneable type.
|
||||
fn into_cloneable(self) -> Self::Cloneable;
|
||||
|
||||
/// Converts this to a cloneable, owned type.
|
||||
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);
|
||||
|
||||
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ pub use element_ext::*;
|
|||
pub use elements::*;
|
||||
pub use inner_html::*;
|
||||
|
||||
/// The typed representation of an HTML element.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct HtmlElement<E, At, Ch, Rndr> {
|
||||
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>
|
||||
for HtmlElement<E, At, Ch, Rndr>
|
||||
where
|
||||
|
@ -136,34 +119,48 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Adds a child to the element.
|
||||
pub trait ElementChild<Rndr, NewChild>
|
||||
where
|
||||
NewChild: Render<Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
/// The type of the element, with the child added.
|
||||
type Output;
|
||||
|
||||
/// Adds a child to an element.
|
||||
fn child(self, child: NewChild) -> Self::Output;
|
||||
}
|
||||
|
||||
/// An HTML element.
|
||||
pub trait ElementType: Send {
|
||||
/// The underlying native widget type that this represents.
|
||||
type Output;
|
||||
|
||||
/// The element's tag.
|
||||
const TAG: &'static str;
|
||||
/// Whether the element is self-closing.
|
||||
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;
|
||||
|
||||
/// The element's tag.
|
||||
fn tag(&self) -> &str;
|
||||
}
|
||||
|
||||
/// Denotes that the type that implements this has a particular HTML element type.
|
||||
pub trait HasElementType {
|
||||
/// The element type.
|
||||
type ElementType;
|
||||
}
|
||||
|
||||
pub trait ElementWithChildren {}
|
||||
pub(crate) trait ElementWithChildren {}
|
||||
|
||||
/// Creates an element.
|
||||
pub trait CreateElement<R: Renderer> {
|
||||
/// Creates an 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
|
||||
where
|
||||
At: Attribute<R>,
|
||||
|
@ -423,10 +421,11 @@ where
|
|||
inner_html
|
||||
}
|
||||
|
||||
/// The retained view state for an HTML element.
|
||||
pub struct ElementState<At, Ch, R: Renderer> {
|
||||
pub el: R::Element,
|
||||
pub attrs: At,
|
||||
pub children: Option<Ch>,
|
||||
pub(crate) el: R::Element,
|
||||
pub(crate) attrs: At,
|
||||
pub(crate) children: Option<Ch>,
|
||||
rndr: PhantomData<R>,
|
||||
}
|
||||
|
||||
|
|
|
@ -14,11 +14,15 @@ use std::{
|
|||
};
|
||||
use wasm_bindgen::convert::FromWasmAbi;
|
||||
|
||||
/// A cloneable event callback.
|
||||
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 {
|
||||
/// Runs the event handler.
|
||||
fn invoke(&mut self, event: E);
|
||||
|
||||
/// Converts this into a cloneable/shared event handler.
|
||||
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> {
|
||||
event: E,
|
||||
el_ty: PhantomData<T>,
|
||||
|
@ -53,10 +58,12 @@ pub struct Targeted<E, T, R> {
|
|||
}
|
||||
|
||||
impl<E, T, R> Targeted<E, T, R> {
|
||||
/// Returns the inner event.
|
||||
pub fn into_inner(self) -> E {
|
||||
self.event
|
||||
}
|
||||
|
||||
/// Returns the event's target, as an HTML element of the correct type.
|
||||
pub fn target(&self) -> T
|
||||
where
|
||||
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>
|
||||
where
|
||||
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)]
|
||||
pub fn on_target<E, T, R, F>(
|
||||
event: E,
|
||||
|
@ -125,6 +134,7 @@ where
|
|||
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> {
|
||||
event: E,
|
||||
cb: SendWrapper<F>,
|
||||
|
@ -153,6 +163,7 @@ where
|
|||
R: DomRenderer,
|
||||
E::EventType: From<R::Event>,
|
||||
{
|
||||
/// Attaches the event listener to the element.
|
||||
pub fn attach(self, el: &R::Element) -> RemoveEventHandler<R::Element> {
|
||||
fn attach_inner<R: DomRenderer>(
|
||||
el: &R::Element,
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
use std::marker::PhantomData;
|
||||
|
||||
// TODO serialized props, too
|
||||
/// An island of interactivity in an otherwise-inert HTML document.
|
||||
pub struct Island<Rndr, View> {
|
||||
component: &'static str,
|
||||
view: View,
|
||||
|
@ -18,6 +19,7 @@ const ISLAND_TAG: &str = "leptos-island";
|
|||
const ISLAND_CHILDREN_TAG: &str = "leptos-children";
|
||||
|
||||
impl<Rndr, View> Island<Rndr, View> {
|
||||
/// Creates a new island with the given component name.
|
||||
pub fn new(component: &'static str, view: View) -> Self {
|
||||
Island {
|
||||
component,
|
||||
|
@ -152,12 +154,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// The children that will be projected into an [`Island`].
|
||||
pub struct IslandChildren<Rndr, View> {
|
||||
view: View,
|
||||
rndr: PhantomData<Rndr>,
|
||||
}
|
||||
|
||||
impl<Rndr, View> IslandChildren<Rndr, View> {
|
||||
/// Creates a new representation of the children.
|
||||
pub fn new(view: View) -> Self {
|
||||
IslandChildren {
|
||||
view,
|
||||
|
|
|
@ -5,21 +5,32 @@ use crate::{
|
|||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Types for HTML attributes.
|
||||
pub mod attribute;
|
||||
/// Types for manipulating the `class` attribute and `classList`.
|
||||
pub mod class;
|
||||
/// Types for creating user-defined attributes with custom behavior (directives).
|
||||
pub mod directive;
|
||||
/// Types for HTML elements.
|
||||
pub mod element;
|
||||
/// Types for DOM events.
|
||||
pub mod event;
|
||||
/// Types for adding interactive islands to inert HTML pages.
|
||||
pub mod islands;
|
||||
/// Types for accessing a reference to an HTML element.
|
||||
pub mod node_ref;
|
||||
/// Types for DOM properties.
|
||||
pub mod property;
|
||||
/// Types for the `style` attribute and individual style manipulation.
|
||||
pub mod style;
|
||||
|
||||
/// A `<!DOCTYPE>` declaration.
|
||||
pub struct Doctype<R: Renderer> {
|
||||
value: &'static str,
|
||||
rndr: PhantomData<R>,
|
||||
}
|
||||
|
||||
/// Creates a `<!DOCTYPE>`.
|
||||
pub fn doctype<R: Renderer>(value: &'static str) -> Doctype<R> {
|
||||
Doctype {
|
||||
value,
|
||||
|
|
|
@ -8,14 +8,17 @@ use crate::{
|
|||
};
|
||||
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
|
||||
where
|
||||
E: ElementType,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
/// Fills the container with the element.
|
||||
fn load(self, el: &Rndr::Element);
|
||||
}
|
||||
|
||||
/// An [`Attribute`] that will fill a [`NodeRefContainer`] with an HTML element.
|
||||
#[derive(Debug)]
|
||||
pub struct NodeRefAttr<E, C, Rndr> {
|
||||
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>
|
||||
where
|
||||
E: ElementType,
|
||||
|
@ -125,6 +129,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Adds the `node_ref` attribute to an element.
|
||||
pub trait NodeRefAttribute<E, C, Rndr>
|
||||
where
|
||||
E: ElementType,
|
||||
|
@ -132,6 +137,7 @@ where
|
|||
Rndr: Renderer,
|
||||
Rndr::Element: PartialEq,
|
||||
{
|
||||
/// Binds this HTML element to a [`NodeRefContainer`].
|
||||
fn node_ref(
|
||||
self,
|
||||
container: C,
|
||||
|
|
|
@ -7,6 +7,7 @@ use send_wrapper::SendWrapper;
|
|||
use std::{borrow::Cow, marker::PhantomData, sync::Arc};
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
/// Creates an [`Attribute`] that will set a DOM property on an element.
|
||||
#[inline(always)]
|
||||
pub fn prop<K, P, R>(key: K, value: P) -> Property<K, P, R>
|
||||
where
|
||||
|
@ -21,6 +22,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// An [`Attribute`] that will set a DOM property on an element.
|
||||
#[derive(Debug)]
|
||||
pub struct Property<K, P, R> {
|
||||
key: K,
|
||||
|
@ -139,23 +141,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A possible value for a DOM property.
|
||||
pub trait IntoProperty<R: DomRenderer> {
|
||||
/// The view state retained between building and rebuilding.
|
||||
type State;
|
||||
/// An equivalent value that can be cloned.
|
||||
type Cloneable: IntoProperty<R> + Clone;
|
||||
/// An equivalent value that can be cloned and is `'static`.
|
||||
type CloneableOwned: IntoProperty<R> + Clone + 'static;
|
||||
|
||||
/// Adds the property on an element created from HTML.
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
el: &R::Element,
|
||||
key: &str,
|
||||
) -> Self::State;
|
||||
|
||||
/// Adds the property during client-side rendering.
|
||||
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);
|
||||
|
||||
/// Converts this to a cloneable type.
|
||||
fn into_cloneable(self) -> Self::Cloneable;
|
||||
|
||||
/// Converts this to a cloneable, owned type.
|
||||
fn into_cloneable_owned(self) -> Self::CloneableOwned;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,9 @@ use crate::{
|
|||
renderer::DomRenderer,
|
||||
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.
|
||||
///
|
||||
/// This can take a plain string value, which will be assigned to the `style`
|
||||
/// Returns an [`Attribute`] that will add to an element's CSS styles.
|
||||
#[inline(always)]
|
||||
pub fn style<S, R>(style: S) -> Style<S, R>
|
||||
where
|
||||
|
@ -22,6 +20,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// An [`Attribute`] that will add to an element's CSS styles.
|
||||
#[derive(Debug)]
|
||||
pub struct Style<S, R> {
|
||||
style: S,
|
||||
|
@ -140,42 +139,43 @@ where
|
|||
/// 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.
|
||||
pub trait IntoStyle<R: DomRenderer>: Send {
|
||||
/// The type after all async data have resolved.
|
||||
type AsyncOutput: IntoStyle<R>;
|
||||
/// The view state retained between building and rebuilding.
|
||||
type State;
|
||||
/// An equivalent value that can be cloned.
|
||||
type Cloneable: IntoStyle<R> + Clone;
|
||||
/// An equivalent value that can be cloned and is `'static`.
|
||||
type CloneableOwned: IntoStyle<R> + Clone + 'static;
|
||||
|
||||
/// Renders the style to HTML.
|
||||
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;
|
||||
|
||||
/// Adds this style to the element during client-side rendering.
|
||||
fn build(self, el: &R::Element) -> Self::State;
|
||||
|
||||
/// Updates the value.
|
||||
fn rebuild(self, state: &mut Self::State);
|
||||
|
||||
/// Converts this to a cloneable type.
|
||||
fn into_cloneable(self) -> Self::Cloneable;
|
||||
|
||||
/// Converts this to a cloneable, owned type.
|
||||
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);
|
||||
|
||||
/// “Resolves” this into a type that is not waiting for any asynchronous data.
|
||||
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
|
||||
where
|
||||
R: DomRenderer,
|
||||
|
|
|
@ -4,6 +4,11 @@ use crate::{
|
|||
};
|
||||
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)]
|
||||
pub struct Cursor<R: Renderer>(Rc<RefCell<R::Node>>);
|
||||
|
||||
|
@ -19,14 +24,19 @@ where
|
|||
|
||||
R::Element: AsRef<R::Node>,
|
||||
{
|
||||
/// Creates a new cursor starting at the root element.
|
||||
pub fn new(root: R::Element) -> Self {
|
||||
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 {
|
||||
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) {
|
||||
//crate::log("advancing to next child of ");
|
||||
//R::log_node(&self.current());
|
||||
|
@ -39,6 +49,9 @@ where
|
|||
//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) {
|
||||
//crate::log("advancing to next sibling of ");
|
||||
//R::log_node(&self.current());
|
||||
|
@ -51,6 +64,9 @@ where
|
|||
//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) {
|
||||
let mut inner = self.0.borrow_mut();
|
||||
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) {
|
||||
*self.0.borrow_mut() = node;
|
||||
}
|
||||
|
||||
/// Advances to the next placeholder node.
|
||||
pub fn next_placeholder(&self, position: &PositionState) -> R::Placeholder {
|
||||
//crate::dom::log("looking for placeholder after");
|
||||
//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
|
||||
#![cfg_attr(feature = "nightly", feature(adt_const_params))]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
/// Commonly-used traits.
|
||||
pub mod prelude {
|
||||
#[cfg(feature = "reactive_graph")]
|
||||
pub use crate::reactive_graph::FutureViewExt;
|
||||
pub use crate::{
|
||||
html::{
|
||||
attribute::{
|
||||
|
@ -29,30 +34,38 @@ pub mod prelude {
|
|||
use wasm_bindgen::JsValue;
|
||||
use web_sys::Node;
|
||||
|
||||
/// Helpers for interacting with the DOM.
|
||||
pub mod dom;
|
||||
/// Types for building a statically-typed HTML view tree.
|
||||
pub mod html;
|
||||
/// Supports adding interactivity to HTML.
|
||||
pub mod hydration;
|
||||
/// Types for MathML.
|
||||
pub mod mathml;
|
||||
/// Defines various backends that can render views.
|
||||
pub mod renderer;
|
||||
/// Rendering views to HTML.
|
||||
pub mod ssr;
|
||||
/// Types for SVG.
|
||||
pub mod svg;
|
||||
/// Core logic for manipulating views.
|
||||
pub mod view;
|
||||
|
||||
pub use either_of as either;
|
||||
#[cfg(feature = "islands")]
|
||||
#[doc(hidden)]
|
||||
pub use wasm_bindgen;
|
||||
#[cfg(feature = "islands")]
|
||||
#[doc(hidden)]
|
||||
pub use web_sys;
|
||||
|
||||
/// View implementations for the `oco_ref` crate (cheaply-cloned string types).
|
||||
#[cfg(feature = "oco")]
|
||||
pub mod oco;
|
||||
/// View implementations for the `reactive_graph` crate.
|
||||
#[cfg(feature = "reactive_graph")]
|
||||
pub mod reactive_graph;
|
||||
|
||||
pub fn log(text: &str) {
|
||||
web_sys::console::log_1(&JsValue::from_str(text));
|
||||
}
|
||||
|
||||
pub(crate) trait UnwrapOrDebug {
|
||||
type Output;
|
||||
|
||||
|
@ -118,6 +131,7 @@ impl<T> UnwrapOrDebug for Result<T, JsValue> {
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! or_debug {
|
||||
($action:expr, $el:expr, $label:literal) => {
|
||||
|
@ -129,6 +143,7 @@ macro_rules! or_debug {
|
|||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! ok_or_debug {
|
||||
($action:expr, $el:expr, $label:literal) => {
|
||||
|
|
|
@ -15,6 +15,7 @@ use std::{fmt::Debug, marker::PhantomData};
|
|||
macro_rules! mathml_global {
|
||||
($tag:ty, $attr:ty) => {
|
||||
paste::paste! {
|
||||
/// A MathML attribute.
|
||||
pub fn $attr<V>(self, value: V) -> HtmlElement <
|
||||
[<$tag:camel>],
|
||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V, Rndr>>,
|
||||
|
@ -47,6 +48,7 @@ macro_rules! mathml_elements {
|
|||
paste::paste! {
|
||||
$(
|
||||
// `tag()` function
|
||||
/// A MathML element.
|
||||
#[track_caller]
|
||||
pub fn $tag<Rndr>() -> HtmlElement<[<$tag:camel>], (), (), Rndr>
|
||||
where
|
||||
|
@ -62,6 +64,7 @@ macro_rules! mathml_elements {
|
|||
}
|
||||
}
|
||||
|
||||
/// A MathML element.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct [<$tag:camel>];
|
||||
|
||||
|
@ -81,6 +84,7 @@ macro_rules! mathml_elements {
|
|||
mathml_global!($tag, scriptlevel);
|
||||
|
||||
$(
|
||||
/// A MathML attribute.
|
||||
pub fn $attr<V>(self, value: V) -> HtmlElement <
|
||||
[<$tag:camel>],
|
||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V, Rndr>>,
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
|||
};
|
||||
use oco_ref::Oco;
|
||||
|
||||
/// Retained view state for [`Oco`].
|
||||
pub struct OcoStrState<R: Renderer> {
|
||||
node: R::Text,
|
||||
str: Oco<'static, str>,
|
||||
|
|
|
@ -20,6 +20,7 @@ use std::{
|
|||
mod class;
|
||||
mod guards;
|
||||
mod inner_html;
|
||||
/// Provides a reactive [`NodeRef`](node_ref::NodeRef) type.
|
||||
pub mod node_ref;
|
||||
mod owned;
|
||||
mod property;
|
||||
|
@ -78,6 +79,8 @@ where
|
|||
old.unmount();
|
||||
}
|
||||
}
|
||||
|
||||
/// Retained view state for a [`RenderEffect`].
|
||||
pub struct RenderEffectState<T: 'static>(Option<RenderEffect<T>>);
|
||||
|
||||
impl<T> From<RenderEffect<T>> for RenderEffectState<T> {
|
||||
|
@ -359,7 +362,9 @@ where
|
|||
|
||||
fn to_html(self, _key: &str, _buf: &mut String) {
|
||||
#[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) {}
|
||||
|
@ -411,12 +416,12 @@ where
|
|||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
#[cfg(feature = "tracing")]
|
||||
tracing::warn!("Suspended attributes cannot be spread");
|
||||
tracing::error!("Suspended attributes cannot be spread");
|
||||
}
|
||||
|
||||
fn into_cloneable_owned(self) -> Self::CloneableOwned {
|
||||
#[cfg(feature = "tracing")]
|
||||
tracing::warn!("Suspended attributes cannot be spread");
|
||||
tracing::error!("Suspended attributes cannot be spread");
|
||||
}
|
||||
|
||||
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>>;
|
||||
|
||||
/// A reactive view function.
|
||||
pub trait ReactiveFunction: Send + 'static {
|
||||
/// The return type of the function.
|
||||
type Output;
|
||||
|
||||
/// Call the function.
|
||||
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>>;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use reactive_graph::{
|
|||
use send_wrapper::SendWrapper;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
/// A reactive reference to a DOM node that can be used with the `node_ref` attribute.
|
||||
#[derive(Debug)]
|
||||
pub struct NodeRef<E>(RwSignal<Option<SendWrapper<E::Output>>>)
|
||||
where
|
||||
|
@ -20,6 +21,7 @@ where
|
|||
E: ElementType,
|
||||
E::Output: 'static,
|
||||
{
|
||||
/// Creates a new node reference.
|
||||
#[track_caller]
|
||||
pub fn new() -> Self {
|
||||
Self(RwSignal::new(None))
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
use reactive_graph::{computed::ScopedFuture, owner::Owner};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// A view wrapper that sets the reactive [`Owner`] to a particular owner whenever it is rendered.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OwnedView<T, R> {
|
||||
owner: Owner,
|
||||
|
@ -37,6 +38,7 @@ impl<T, R> OwnedView<T, R> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Retained view state for an [`OwnedView`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OwnedViewState<T, R>
|
||||
where
|
||||
|
|
|
@ -19,25 +19,7 @@ use reactive_graph::{
|
|||
};
|
||||
use std::{cell::RefCell, fmt::Debug, future::Future, pin::Pin, rc::Rc};
|
||||
|
||||
pub trait FutureViewExt: Sized {
|
||||
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 })
|
||||
};
|
||||
}*/
|
||||
|
||||
/// A suspended `Future`, which can be used in the view.
|
||||
#[derive(Clone)]
|
||||
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>
|
||||
where
|
||||
T: Render<Rndr>,
|
||||
|
|
|
@ -14,6 +14,7 @@ use web_sys::{
|
|||
Event, HtmlElement, HtmlTemplateElement, Node, Text,
|
||||
};
|
||||
|
||||
/// A [`Renderer`] that uses `web-sys` to manipulate DOM elements in the browser.
|
||||
#[derive(Debug)]
|
||||
pub struct Dom;
|
||||
|
||||
|
@ -37,7 +38,12 @@ impl Renderer for Dom {
|
|||
}
|
||||
|
||||
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"))]
|
||||
|
|
|
@ -13,22 +13,31 @@ use slotmap::{new_key_type, SlotMap};
|
|||
use std::{borrow::Cow, cell::RefCell, collections::HashMap, rc::Rc};
|
||||
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)]
|
||||
pub struct MockDom;
|
||||
|
||||
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)]
|
||||
pub struct Node(NodeId);
|
||||
|
||||
/// A mock element.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
pub struct Element(Node);
|
||||
|
||||
/// A mock text node.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
pub struct Text(Node);
|
||||
|
||||
/// A mock comment node.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
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 {
|
||||
a.as_ref() == b.as_ref()
|
||||
}
|
||||
|
@ -79,6 +89,7 @@ impl From<Placeholder> for Node {
|
|||
}
|
||||
|
||||
impl Element {
|
||||
/// Outputs an HTML form of the element, for testing and debugging purposes.
|
||||
pub fn to_debug_html(&self) -> String {
|
||||
let mut buf = String::new();
|
||||
self.debug_html(&mut buf);
|
||||
|
@ -86,9 +97,12 @@ impl Element {
|
|||
}
|
||||
}
|
||||
|
||||
/// The DOM data associated with a particular node.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct NodeData {
|
||||
parent: Option<NodeId>,
|
||||
/// The node's parent.
|
||||
pub parent: Option<NodeId>,
|
||||
/// The node itself.
|
||||
pub ty: NodeType,
|
||||
}
|
||||
|
||||
|
@ -153,10 +167,12 @@ impl DebugHtml for NodeData {
|
|||
}
|
||||
}
|
||||
|
||||
/// The mock DOM document.
|
||||
#[derive(Clone)]
|
||||
pub struct Document(Rc<RefCell<SlotMap<NodeId, NodeData>>>);
|
||||
|
||||
impl Document {
|
||||
/// Creates a new document.
|
||||
pub fn new() -> Self {
|
||||
Document(Default::default())
|
||||
}
|
||||
|
@ -180,6 +196,7 @@ impl Document {
|
|||
})
|
||||
}
|
||||
|
||||
/// Resets the document's contents.
|
||||
pub fn reset(&self) {
|
||||
self.0.borrow_mut().clear();
|
||||
}
|
||||
|
@ -295,18 +312,26 @@ thread_local! {
|
|||
static DOCUMENT: Document = Document::new();
|
||||
}
|
||||
|
||||
/// Returns the global document.
|
||||
pub fn document() -> Document {
|
||||
DOCUMENT.with(Clone::clone)
|
||||
}
|
||||
|
||||
/// The type of mock DOM node.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum NodeType {
|
||||
/// A text node.
|
||||
Text(String),
|
||||
/// An element.
|
||||
Element {
|
||||
/// The HTML tag name.
|
||||
tag: Cow<'static, str>,
|
||||
/// The attributes.
|
||||
attrs: HashMap<String, String>,
|
||||
/// The element's children.
|
||||
children: Vec<Node>,
|
||||
},
|
||||
/// A placeholder.
|
||||
Placeholder,
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,12 @@ use crate::{
|
|||
use std::{borrow::Cow, fmt::Debug};
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
/// A DOM renderer.
|
||||
pub mod dom;
|
||||
#[cfg(feature = "testing")]
|
||||
/// A renderer based on a mock DOM.
|
||||
pub mod mock_dom;
|
||||
/// A DOM renderer optimized for element creation.
|
||||
#[cfg(feature = "sledgehammer")]
|
||||
pub mod sledgehammer;
|
||||
|
||||
|
@ -38,6 +41,7 @@ pub trait Renderer: Send + Sized + Debug + 'static {
|
|||
+ Clone
|
||||
+ 'static;
|
||||
|
||||
/// Interns a string slice, if that is available on this platform and useful as an optimization.
|
||||
fn intern(text: &str) -> &str;
|
||||
|
||||
/// 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.
|
||||
fn next_sibling(node: &Self::Node) -> Option<Self::Node>;
|
||||
|
||||
/// Logs the given node in a platform-appropriate way.
|
||||
fn log_node(node: &Self::Node);
|
||||
}
|
||||
|
||||
|
@ -208,7 +213,7 @@ pub trait DomRenderer: Renderer {
|
|||
fn get_template<V>() -> Self::TemplateElement
|
||||
where
|
||||
V: ToTemplate + 'static;
|
||||
|
||||
/// Deeply clones a template.
|
||||
fn clone_template(tpl: &Self::TemplateElement) -> Self::Element;
|
||||
}
|
||||
|
||||
|
@ -222,5 +227,6 @@ pub trait CastFrom<T>
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// Casts a node from one type to another.
|
||||
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::{
|
||||
dom::window,
|
||||
view::{Mountable, ToTemplate},
|
||||
|
@ -374,7 +376,7 @@ impl DomRenderer for Sledgehammer {
|
|||
el: &Self::Element,
|
||||
name: &str,
|
||||
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();
|
||||
CHANNEL.with_borrow_mut(|channel| {
|
||||
channel.add_listener(el.0 .0, name);
|
||||
|
@ -383,7 +385,7 @@ impl DomRenderer for Sledgehammer {
|
|||
});
|
||||
|
||||
// return the remover
|
||||
Box::new(move |_el| todo!())
|
||||
RemoveEventHandler(Box::new(move |_el| todo!()))
|
||||
}
|
||||
|
||||
fn event_target<T>(_ev: &Self::Event) -> T
|
||||
|
@ -404,7 +406,7 @@ impl DomRenderer for Sledgehammer {
|
|||
name: Cow<'static, str>,
|
||||
delegation_key: Cow<'static, str>,
|
||||
cb: Box<dyn FnMut(Self::Event)>,
|
||||
) -> Box<dyn FnOnce(&Self::Element) + Send> {
|
||||
) -> RemoveEventHandler<Self::Element> {
|
||||
let cb = Closure::wrap(cb).into_js_value();
|
||||
CHANNEL.with_borrow_mut(|channel| {
|
||||
channel.set_property(el.0 .0, &delegation_key);
|
||||
|
@ -481,7 +483,7 @@ impl DomRenderer for Sledgehammer {
|
|||
});
|
||||
|
||||
// return the remover
|
||||
Box::new(move |_el| todo!())
|
||||
RemoveEventHandler(Box::new(move |_el| todo!()))
|
||||
}
|
||||
|
||||
fn class_list(el: &Self::Element) -> Self::ClassList {
|
||||
|
|
|
@ -12,10 +12,11 @@ use std::{
|
|||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
/// Manages streaming HTML rendering for the response to a single request.
|
||||
#[derive(Default)]
|
||||
pub struct StreamBuilder {
|
||||
sync_buf: String,
|
||||
pub chunks: VecDeque<StreamChunk>,
|
||||
pub(crate) chunks: VecDeque<StreamChunk>,
|
||||
pending: Option<ChunkFuture>,
|
||||
pending_ooo: VecDeque<PinnedFuture<OooChunk>>,
|
||||
id: Option<Vec<u16>>,
|
||||
|
@ -25,10 +26,12 @@ type PinnedFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
|
|||
type ChunkFuture = PinnedFuture<VecDeque<StreamChunk>>;
|
||||
|
||||
impl StreamBuilder {
|
||||
/// Creates a new HTML stream.
|
||||
pub fn new(id: Option<Vec<u16>>) -> Self {
|
||||
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 {
|
||||
Self {
|
||||
id,
|
||||
|
@ -37,14 +40,17 @@ impl StreamBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reserves additional space in the synchronous buffer.
|
||||
pub fn reserve(&mut self, additional: usize) {
|
||||
self.sync_buf.reserve(additional);
|
||||
}
|
||||
|
||||
/// Pushes text into the synchronous buffer.
|
||||
pub fn push_sync(&mut self, string: &str) {
|
||||
self.sync_buf.push_str(string);
|
||||
}
|
||||
|
||||
/// Pushes an async block into the stream.
|
||||
pub fn push_async(
|
||||
&mut self,
|
||||
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)) {
|
||||
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> {
|
||||
let sync = mem::take(&mut self.sync_buf);
|
||||
if !sync.is_empty() {
|
||||
|
@ -71,11 +79,13 @@ impl StreamBuilder {
|
|||
mem::take(&mut self.chunks)
|
||||
}
|
||||
|
||||
/// Appends another stream to this one.
|
||||
pub fn append(&mut self, mut other: StreamBuilder) {
|
||||
self.chunks.append(&mut other.chunks);
|
||||
self.sync_buf.push_str(&other.sync_buf);
|
||||
}
|
||||
|
||||
/// Completes the stream.
|
||||
pub fn finish(mut self) -> Self {
|
||||
let sync_buf_remaining = mem::take(&mut self.sync_buf);
|
||||
if sync_buf_remaining.is_empty() {
|
||||
|
@ -89,6 +99,7 @@ impl StreamBuilder {
|
|||
}
|
||||
|
||||
// Out-of-Order Streaming
|
||||
/// Pushes a fallback for out-of-order streaming.
|
||||
pub fn push_fallback<View, Rndr>(
|
||||
&mut self,
|
||||
fallback: View,
|
||||
|
@ -103,16 +114,19 @@ impl StreamBuilder {
|
|||
*position = Position::NextChild;
|
||||
}
|
||||
|
||||
/// Increments the chunk ID.
|
||||
pub fn next_id(&mut self) {
|
||||
if let Some(last) = self.id.as_mut().and_then(|ids| ids.last_mut()) {
|
||||
*last += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current ID.
|
||||
pub fn clone_id(&self) -> Option<Vec<u16>> {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
/// Returns an ID that is a child of the current one.
|
||||
pub fn child_id(&self) -> Option<Vec<u16>> {
|
||||
let mut child = self.id.clone();
|
||||
if let Some(child) = child.as_mut() {
|
||||
|
@ -121,6 +135,7 @@ impl StreamBuilder {
|
|||
child
|
||||
}
|
||||
|
||||
/// Inserts a marker for the current out-of-order chunk.
|
||||
pub fn write_chunk_marker(&mut self, opening: bool) {
|
||||
if let Some(id) = &self.id {
|
||||
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>(
|
||||
&mut self,
|
||||
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 {
|
||||
/// Some synchronously-available HTML.
|
||||
Sync(String),
|
||||
/// The chunk can be rendered asynchronously in order.
|
||||
Async {
|
||||
/// A collection of in-order chunks.
|
||||
chunks: PinnedFuture<VecDeque<StreamChunk>>,
|
||||
},
|
||||
/// The chunk can be rendered asynchronously out of order.
|
||||
OutOfOrder {
|
||||
/// A collection of out-of-order chunks
|
||||
chunks: PinnedFuture<OooChunk>,
|
||||
},
|
||||
}
|
||||
|
||||
/// A chunk of the out-of-order stream.
|
||||
#[derive(Debug)]
|
||||
pub struct OooChunk {
|
||||
id: String,
|
||||
|
@ -211,6 +234,7 @@ pub struct OooChunk {
|
|||
}
|
||||
|
||||
impl OooChunk {
|
||||
/// Pushes an opening `<template>` tag into the buffer.
|
||||
pub fn push_start(id: &str, buf: &mut String) {
|
||||
buf.push_str("<template id=\"");
|
||||
buf.push_str(id);
|
||||
|
@ -218,6 +242,7 @@ impl OooChunk {
|
|||
buf.push_str("\">");
|
||||
}
|
||||
|
||||
/// Pushes a closing `</template>` and update script into the buffer.
|
||||
pub fn push_end(replace: bool, id: &str, buf: &mut String) {
|
||||
buf.push_str("</template>");
|
||||
|
||||
|
@ -411,6 +436,7 @@ impl Stream for StreamBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
|
@ -635,3 +661,4 @@ mod tests {
|
|||
assert!(stream.next().await.is_none());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -15,6 +15,7 @@ macro_rules! svg_elements {
|
|||
($($tag:ident [$($attr:ty),*]),* $(,)?) => {
|
||||
paste::paste! {
|
||||
$(
|
||||
/// An SVG attribute.
|
||||
// `tag()` function
|
||||
#[allow(non_snake_case)]
|
||||
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)]
|
||||
pub struct [<$tag:camel>];
|
||||
|
||||
|
|
|
@ -12,8 +12,10 @@ pub trait AddAnyAttr<Rndr>
|
|||
where
|
||||
Rndr: Renderer,
|
||||
{
|
||||
/// The new type once the attribute has been added.
|
||||
type Output<SomeNewAttr: Attribute<Rndr>>: RenderHtml<Rndr>;
|
||||
|
||||
/// Adds an attribute to the view.
|
||||
fn add_any_attr<NewAttr: Attribute<Rndr>>(
|
||||
self,
|
||||
attr: NewAttr,
|
||||
|
@ -22,6 +24,7 @@ where
|
|||
Self::Output<NewAttr>: RenderHtml<Rndr>;
|
||||
}
|
||||
|
||||
/// Declares that spreading attributes onto a particular type has no effect.
|
||||
#[macro_export]
|
||||
macro_rules! no_attrs {
|
||||
($ty_name:ty) => {
|
||||
|
|
|
@ -14,6 +14,16 @@ use std::{
|
|||
#[cfg(feature = "ssr")]
|
||||
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>
|
||||
where
|
||||
R: Renderer,
|
||||
|
@ -49,6 +59,7 @@ where
|
|||
fn(Box<dyn Any>, &Cursor<R>, &PositionState) -> AnyViewState<R>,
|
||||
}
|
||||
|
||||
/// Retained view state for [`AnyView`].
|
||||
pub struct AnyViewState<R>
|
||||
where
|
||||
R: Renderer,
|
||||
|
@ -77,10 +88,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Allows converting some view into [`AnyView`].
|
||||
pub trait IntoAny<R>
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
/// Converts the view into a type-erased [`AnyView`].
|
||||
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.
|
||||
pub struct EitherKeepAlive<A, B> {
|
||||
/// The first possibility.
|
||||
pub a: Option<A>,
|
||||
/// The second possibility.
|
||||
pub b: Option<B>,
|
||||
/// If `true`, then `b` will be shown.
|
||||
pub show_b: bool,
|
||||
}
|
||||
|
||||
/// Retained view state for [`EitherKeepAlive`].
|
||||
pub struct EitherKeepAliveState<A, B> {
|
||||
a: Option<A>,
|
||||
b: Option<B>,
|
||||
|
@ -392,12 +396,15 @@ where
|
|||
macro_rules! tuples {
|
||||
($num:literal => $($ty:ident),*) => {
|
||||
paste::paste! {
|
||||
#[doc = concat!("Retained view state for ", stringify!([<EitherOf $num>]), ".")]
|
||||
pub struct [<EitherOf $num State>]<$($ty,)* Rndr>
|
||||
where
|
||||
$($ty: Render<Rndr>,)*
|
||||
Rndr: Renderer
|
||||
{
|
||||
/// Which child view state is being displayed.
|
||||
pub state: [<EitherOf $num>]<$($ty::State,)*>,
|
||||
/// The renderer.
|
||||
pub rndr: PhantomData<Rndr>
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ pub struct Fragment<R: Renderer> {
|
|||
pub nodes: Vec<AnyView<R>>,
|
||||
}
|
||||
|
||||
/// Converts some view into a type-erased collection of views.
|
||||
pub trait IntoFragment<R: Renderer> {
|
||||
/// Converts some view into a type-erased collection of views.
|
||||
fn into_fragment(self) -> Fragment<R>;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
use either_of::Either;
|
||||
use itertools::Itertools;
|
||||
|
||||
/// Retained view state for an `Option`.
|
||||
pub type OptionState<T, R> =
|
||||
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>
|
||||
where
|
||||
T: Mountable<R>,
|
||||
|
|
|
@ -18,6 +18,7 @@ use std::{
|
|||
|
||||
type FxIndexSet<T> = IndexSet<T, BuildHasherDefault<FxHasher>>;
|
||||
|
||||
/// Creates a keyed list of views.
|
||||
pub fn keyed<T, I, K, KF, VF, V, Rndr>(
|
||||
items: I,
|
||||
key_fn: KF,
|
||||
|
@ -39,6 +40,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A keyed list of views.
|
||||
pub struct Keyed<T, I, K, KF, VF, V, Rndr>
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
|
@ -53,6 +55,7 @@ where
|
|||
rndr: PhantomData<Rndr>,
|
||||
}
|
||||
|
||||
/// Retained view state for a keyed list.
|
||||
pub struct KeyedState<K, V, Rndr>
|
||||
where
|
||||
K: Eq + Hash + 'static,
|
||||
|
|
|
@ -3,18 +3,29 @@ use crate::{hydration::Cursor, renderer::Renderer, ssr::StreamBuilder};
|
|||
use parking_lot::RwLock;
|
||||
use std::{cell::RefCell, future::Future, rc::Rc, sync::Arc};
|
||||
|
||||
/// Add attributes to typed views.
|
||||
pub mod add_attr;
|
||||
/// A typed-erased view type.
|
||||
pub mod any_view;
|
||||
/// Allows choosing between one of several views.
|
||||
pub mod either;
|
||||
/// View rendering for `Result<_, _>` types.
|
||||
pub mod error_boundary;
|
||||
/// A type-erased view collection.
|
||||
pub mod fragment;
|
||||
/// View implementations for several iterable types.
|
||||
pub mod iterators;
|
||||
/// Keyed list iteration.
|
||||
pub mod keyed;
|
||||
mod primitives;
|
||||
/// Optimized types for static strings known at compile time.
|
||||
#[cfg(feature = "nightly")]
|
||||
pub mod static_types;
|
||||
/// View implementation for string types.
|
||||
pub mod strings;
|
||||
/// Optimizations for creating views via HTML `<template>` nodes.
|
||||
pub mod template;
|
||||
/// View implementations for tuples.
|
||||
pub mod tuples;
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
#[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
|
||||
/// that HTML into an interactive interface.
|
||||
///
|
||||
|
@ -65,11 +65,15 @@ where
|
|||
/// The type of the view after waiting for all asynchronous data to load.
|
||||
type AsyncOutput: RenderHtml<R>;
|
||||
|
||||
/// The minimum length of HTML created when this view is rendered.
|
||||
const MIN_LENGTH: usize;
|
||||
|
||||
/// Whether this should actually exist in the DOM, if it is the child of an element.
|
||||
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);
|
||||
|
||||
/// 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.
|
||||
pub trait ToTemplate {
|
||||
/// The HTML content of the static template.
|
||||
const TEMPLATE: &'static str = "";
|
||||
/// The `class` attribute content known at compile time.
|
||||
const CLASS: &'static str = "";
|
||||
/// The `style` attribute content known at compile time.
|
||||
const STYLE: &'static str = "";
|
||||
/// The length of the template.
|
||||
const LEN: usize = Self::TEMPLATE.as_bytes().len();
|
||||
|
||||
/// 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)]
|
||||
pub struct PositionState(Arc<RwLock<Position>>);
|
||||
|
||||
impl PositionState {
|
||||
/// Creates a new position tracker.
|
||||
pub fn new(position: Position) -> Self {
|
||||
Self(Arc::new(RwLock::new(position)))
|
||||
}
|
||||
|
||||
/// Sets the current position.
|
||||
pub fn set(&self, position: Position) {
|
||||
*self.0.write() = position;
|
||||
}
|
||||
|
||||
/// Gets the current position.
|
||||
pub fn get(&self) -> Position {
|
||||
*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 {
|
||||
let current = self.get();
|
||||
Self(Arc::new(RwLock::new(current)))
|
||||
}
|
||||
}
|
||||
|
||||
/// The position of this element, relative to others.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
|
||||
pub enum Position {
|
||||
/// This is the current node.
|
||||
Current,
|
||||
/// This is the first child of its parent.
|
||||
#[default]
|
||||
FirstChild,
|
||||
/// This is the next child after another child.
|
||||
NextChild,
|
||||
/// This is the next child after a text node.
|
||||
NextChildAfterText,
|
||||
/// This is the only child of its parent.
|
||||
OnlyChild,
|
||||
/// This is the last child of its parent.
|
||||
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>
|
||||
{
|
||||
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)]
|
||||
pub struct Static<const V: &'static str>;
|
||||
|
||||
|
|
|
@ -13,8 +13,9 @@ no_attrs!(String);
|
|||
no_attrs!(Arc<str>);
|
||||
no_attrs!(Cow<'a, str>);
|
||||
|
||||
/// Retained view state for `&str`.
|
||||
pub struct StrState<'a, R: Renderer> {
|
||||
pub node: R::Text,
|
||||
pub(crate) node: R::Text,
|
||||
str: &'a str,
|
||||
}
|
||||
|
||||
|
@ -142,6 +143,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Retained view state for `String`.
|
||||
pub struct StringState<R: Renderer> {
|
||||
node: R::Text,
|
||||
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> {
|
||||
node: R::Text,
|
||||
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> {
|
||||
node: R::Text,
|
||||
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> {
|
||||
node: R::Text,
|
||||
str: Cow<'a, str>,
|
||||
|
|
|
@ -7,6 +7,11 @@ use crate::{
|
|||
};
|
||||
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> {
|
||||
view: V,
|
||||
rndr: PhantomData<R>,
|
||||
|
@ -17,6 +22,7 @@ where
|
|||
V: Render<R> + ToTemplate + 'static,
|
||||
R: DomRenderer,
|
||||
{
|
||||
/// Creates a new view template.
|
||||
pub fn new(view: V) -> Self {
|
||||
Self {
|
||||
view,
|
||||
|
|
Loading…
Reference in a new issue