Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xilem_web: Add a few boolean attribute modifiers for HtmlInputElement and factor element state flags out of these modifiers into ElementFlags #717

Merged
134 changes: 0 additions & 134 deletions xilem_web/src/element_props.rs

This file was deleted.

4 changes: 2 additions & 2 deletions xilem_web/src/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ pub(crate) fn rebuild_element<State, Action, Element>(
{
let mut dom_children_splice = DomChildrenSplice::new(
&mut state.append_scratch,
With::<Children>::modifier(element.props),
With::<Children>::modifier(element.props).modifier,
&mut state.vec_splice_scratch,
element.node.as_ref(),
ctx.fragment.clone(),
Expand Down Expand Up @@ -294,7 +294,7 @@ pub(crate) fn teardown_element<State, Action, Element>(
{
let mut dom_children_splice = DomChildrenSplice::new(
&mut state.append_scratch,
With::<Children>::modifier(element.props),
With::<Children>::modifier(element.props).modifier,
&mut state.vec_splice_scratch,
element.node.as_ref(),
ctx.fragment.clone(),
Expand Down
101 changes: 88 additions & 13 deletions xilem_web/src/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ use std::borrow::Cow;

use crate::{
events,
modifiers::{
Attr, Attributes, Class, ClassIter, Classes, Rotate, Scale, ScaleValue, Style, StyleIter,
Styles, With,
},
modifiers::{Attr, Class, ClassIter, Rotate, Scale, ScaleValue, Style, StyleIter},
props::{WithElementProps, WithHtmlInputElementProps},
DomNode, DomView, IntoAttributeValue, OptionalAction, Pointer, PointerMsg,
};
use wasm_bindgen::JsCast;
Expand Down Expand Up @@ -51,13 +49,7 @@ macro_rules! event_handler_mixin {
}

pub trait Element<State, Action = ()>:
Sized
+ DomView<
State,
Action,
DomNode: DomNode<Props: With<Attributes> + With<Classes> + With<Styles>>
+ AsRef<web_sys::Element>,
>
Sized + DomView<State, Action, DomNode: DomNode<Props: WithElementProps> + AsRef<web_sys::Element>>
{
/// Set an attribute for an [`Element`]
///
Expand Down Expand Up @@ -331,7 +323,7 @@ pub trait Element<State, Action = ()>:
impl<State, Action, T> Element<State, Action> for T
where
T: DomView<State, Action>,
<T::DomNode as DomNode>::Props: With<Attributes> + With<Classes> + With<Styles>,
<T::DomNode as DomNode>::Props: WithElementProps,
T::DomNode: AsRef<web_sys::Element>,
{
}
Expand Down Expand Up @@ -758,17 +750,100 @@ where
{
}

use crate::modifiers::html_input_element;
// #[cfg(feature = "HtmlInputElement")]
pub trait HtmlInputElement<State, Action = ()>:
HtmlElement<State, Action, DomNode: AsRef<web_sys::HtmlInputElement>>
HtmlElement<
State,
Action,
DomNode: DomNode<Props: WithHtmlInputElementProps> + AsRef<web_sys::HtmlInputElement>,
>
{
/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/checked> for more details.
///
/// # Examples
///
/// ```
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
///
/// # fn component() -> impl HtmlInputElement<()> {
/// input(()).attr("type", "checkbox").checked(true) // results in <input type="checkbox" checked></input>
/// # }
/// ```
fn checked(self, checked: bool) -> html_input_element::view::Checked<Self, State, Action> {
html_input_element::view::Checked::new(self, checked)
}

/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/checked> for more details.
///
/// # Examples
///
/// ```
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
///
/// # fn component() -> impl HtmlInputElement<()> {
/// input(()).attr("type", "radio").default_checked(true) // results in <input type="radio" checked></input>
/// # }
/// ```
fn default_checked(
self,
default_checked: bool,
) -> html_input_element::view::DefaultChecked<Self, State, Action> {
html_input_element::view::DefaultChecked::new(self, default_checked)
}

/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/disabled> for more details.
///
/// # Examples
///
/// ```
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
///
/// # fn component() -> impl HtmlInputElement<()> {
/// input(()).disabled(true) // results in <input disabled></input>
/// # }
/// ```
fn disabled(self, disabled: bool) -> html_input_element::view::Disabled<Self, State, Action> {
html_input_element::view::Disabled::new(self, disabled)
}

/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/disabled> for more details.
///
/// # Examples
///
/// ```
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
///
/// # fn component() -> impl HtmlInputElement<()> {
/// input(()).required(true) // results in <input required></input>
/// # }
/// ```
fn required(self, required: bool) -> html_input_element::view::Required<Self, State, Action> {
html_input_element::view::Required::new(self, required)
}

/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/multiple> for more details.
///
/// # Examples
///
/// ```
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
///
/// # fn component() -> impl HtmlInputElement<()> {
/// input(()).required(true) // results in <input required></input>
/// # }
/// ```
fn multiple(self, required: bool) -> html_input_element::view::Multiple<Self, State, Action> {
RagibHasin marked this conversation as resolved.
Show resolved Hide resolved
html_input_element::view::Multiple::new(self, required)
}
Copy link
Contributor

@RagibHasin RagibHasin Oct 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a copy-paste artifact. That is the parameter should be named multiple as well and the doc is wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this, I went over the rest of the doc-comments and have found a few inconsistencies as well.
I hope I have now found and fixed all...
I've also renamed With to WithModifier as it seems more appropriate, and it's likely summed up in these alias traits anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've also renamed With to WithModifier as it seems more appropriate

👍 It looks like a small change, but from my point of view it is enormously helpful for readability! 👍

}

// #[cfg(feature = "HtmlInputElement")]
impl<State, Action, T> HtmlInputElement<State, Action> for T
where
T: HtmlElement<State, Action>,
T::DomNode: AsRef<web_sys::HtmlInputElement>,
<T::DomNode as DomNode>::Props: WithHtmlInputElementProps,
{
}

Expand Down
31 changes: 19 additions & 12 deletions xilem_web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ mod app;
mod attribute_value;
mod context;
mod dom_helpers;
mod element_props;
mod message;
mod one_of;
mod optional_action;
Expand All @@ -48,6 +47,7 @@ pub mod elements;
pub mod events;
pub mod interfaces;
pub mod modifiers;
pub mod props;
pub mod svg;

pub use self::{
Expand All @@ -58,7 +58,6 @@ pub use self::{
attribute_value::{AttributeValue, IntoAttributeValue},
context::{MessageThunk, ViewCtx},
dom_helpers::{document, document_body, get_element_by_id, input_event_target_value},
element_props::ElementProps,
message::{DynMessage, Message},
optional_action::{Action, OptionalAction},
pointer::{Pointer, PointerDetails, PointerMsg},
Expand Down Expand Up @@ -251,11 +250,11 @@ pub struct Pod<N: DomNode> {
pub type AnyPod = Pod<Box<dyn AnyNode>>;

impl<N: DomNode> Pod<N> {
pub fn into_any_pod(node: N, mut props: N::Props) -> AnyPod {
node.apply_props(&mut props);
pub fn into_any_pod(mut pod: Pod<N>) -> AnyPod {
pod.node.apply_props(&mut pod.props);
Pod {
node: Box::new(node),
props: Box::new(props),
node: Box::new(pod.node),
props: Box::new(pod.props),
}
}
}
Expand All @@ -281,7 +280,7 @@ impl<N: DomNode> ViewElement for Pod<N> {

impl<N: DomNode> SuperElement<Pod<N>, ViewCtx> for AnyPod {
fn upcast(_ctx: &mut ViewCtx, child: Pod<N>) -> Self {
Pod::into_any_pod(child.node, child.props)
Pod::into_any_pod(child)
}

fn with_downcast_val<R>(
Expand Down Expand Up @@ -389,9 +388,9 @@ impl<T, N: AsRef<T> + DomNode> AsRef<T> for PodMut<'_, N> {
}

impl DomNode for web_sys::Element {
type Props = ElementProps;
type Props = props::Element;

fn apply_props(&self, props: &mut ElementProps) {
fn apply_props(&self, props: &mut props::Element) {
props.update_element(self);
}
}
Expand All @@ -402,6 +401,14 @@ impl DomNode for web_sys::Text {
fn apply_props(&self, (): &mut ()) {}
}

impl DomNode for web_sys::HtmlInputElement {
type Props = props::HtmlInputElement;

fn apply_props(&self, props: &mut props::HtmlInputElement) {
props.update_element(self);
}
}

pub trait FromWithContext<T>: Sized {
fn from_with_ctx(value: T, ctx: &mut ViewCtx) -> Self;
}
Expand All @@ -416,9 +423,9 @@ impl<T> FromWithContext<T> for T {
macro_rules! impl_dom_node_for_elements {
($($ty:ident, )*) => {$(
impl DomNode for web_sys::$ty {
type Props = ElementProps;
type Props = props::Element;

fn apply_props(&self, props: &mut ElementProps) {
fn apply_props(&self, props: &mut props::Element) {
props.update_element(self);
}
}
Expand Down Expand Up @@ -464,7 +471,7 @@ impl_dom_node_for_elements!(
// HtmlHtmlElement, TODO include metadata?
HtmlIFrameElement,
HtmlImageElement,
HtmlInputElement,
// HtmlInputElement, has specialized impl
HtmlLabelElement,
HtmlLegendElement,
HtmlLiElement,
Expand Down
Loading