Fix HtmlSelect not resetting properly when value changed (#145)

This commit is contained in:
Cecile Tonglet 2022-08-22 15:15:22 +01:00 committed by GitHub
parent 44d0b453b1
commit 90ce9a15a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 200 additions and 166 deletions

View file

@ -12,9 +12,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: Swatinem/rust-cache@v1 - uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- run: cargo test --workspace --all-features --verbose - run: cargo test --workspace --all-features --verbose
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: rustup install --profile default nightly - run: rustup install --profile default nightly
# NOTE: we use nightly here to enable the options error_on_line_overflow and # NOTE: we use nightly here to enable the options error_on_line_overflow and

View file

@ -2,7 +2,7 @@
name = "yewprint" name = "yewprint"
version = "0.2.0" version = "0.2.0"
authors = ["Cecile Tonglet <cecile.tonglet@cecton.com>"] authors = ["Cecile Tonglet <cecile.tonglet@cecton.com>"]
edition = "2018" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "Port of blueprintjs.com to Yew" description = "Port of blueprintjs.com to Yew"
repository = "https://github.com/yewprint/yewprint" repository = "https://github.com/yewprint/yewprint"

View file

@ -46,7 +46,7 @@ fn main() {
let mut keys: Vec<_> = keys.iter().collect(); let mut keys: Vec<_> = keys.iter().collect();
keys.sort(); keys.sort();
src.push_str("#[derive(Debug, Copy, Clone, PartialEq)]\npub enum IconName {\n"); src.push_str("#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\npub enum IconName {\n");
for icon in keys { for icon in keys {
src.push_str(icon); src.push_str(icon);
src.push_str(",\n"); src.push_str(",\n");

View file

@ -4,11 +4,13 @@ use crate::{Icon, IconName};
use web_sys::HtmlSelectElement; use web_sys::HtmlSelectElement;
use yew::prelude::*; use yew::prelude::*;
#[derive(Debug)]
pub struct HtmlSelect<T: Clone + PartialEq + 'static> { pub struct HtmlSelect<T: Clone + PartialEq + 'static> {
select_element: NodeRef,
phantom: PhantomData<T>, phantom: PhantomData<T>,
} }
#[derive(Clone, PartialEq, Properties)] #[derive(Debug, Clone, PartialEq, Properties)]
pub struct HtmlSelectProps<T: Clone + PartialEq + 'static> { pub struct HtmlSelectProps<T: Clone + PartialEq + 'static> {
#[prop_or_default] #[prop_or_default]
pub fill: bool, pub fill: bool,
@ -37,6 +39,7 @@ impl<T: Clone + PartialEq + 'static> Component for HtmlSelect<T> {
fn create(_ctx: &Context<Self>) -> Self { fn create(_ctx: &Context<Self>) -> Self {
Self { Self {
select_element: NodeRef::default(),
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -55,6 +58,21 @@ impl<T: Clone + PartialEq + 'static> Component for HtmlSelect<T> {
false false
} }
fn changed(&mut self, ctx: &Context<Self>) -> bool {
if let Some(value) = ctx.props().value.as_ref() {
if let Some(select) = self.select_element.cast::<HtmlSelectElement>() {
if let Some(i) = ctx.props().options.iter().position(|(x, _)| x == value) {
if let Ok(i) = i.try_into() {
if select.selected_index() != i {
select.set_selected_index(i);
}
}
}
}
}
true
}
fn view(&self, ctx: &Context<Self>) -> Html { fn view(&self, ctx: &Context<Self>) -> Html {
let option_children = ctx let option_children = ctx
.props() .props()
@ -92,6 +110,7 @@ impl<T: Clone + PartialEq + 'static> Component for HtmlSelect<T> {
onchange={ctx.link().callback(|x| x)} onchange={ctx.link().callback(|x| x)}
title={ctx.props().title.clone()} title={ctx.props().title.clone()}
value={"".to_string()} value={"".to_string()}
ref={self.select_element.clone()}
> >
{option_children} {option_children}
</select> </select>

View file

@ -3,6 +3,7 @@ use yew::prelude::*;
const MIN_HORIZONTAL_PADDING: i32 = 10; const MIN_HORIZONTAL_PADDING: i32 = 10;
#[derive(Debug)]
pub struct InputGroup { pub struct InputGroup {
left_element_ref: NodeRef, left_element_ref: NodeRef,
left_element_width: Option<i32>, left_element_width: Option<i32>,
@ -10,7 +11,7 @@ pub struct InputGroup {
right_element_width: Option<i32>, right_element_width: Option<i32>,
} }
#[derive(Copy, Clone, PartialEq, Debug, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TextInputType { pub enum TextInputType {
Text, Text,
Password, Password,

View file

@ -2,7 +2,8 @@
clippy::redundant_closure, clippy::redundant_closure,
clippy::needless_update, clippy::needless_update,
clippy::inconsistent_struct_constructor, clippy::inconsistent_struct_constructor,
clippy::type_complexity clippy::type_complexity,
clippy::derive_partial_eq_without_eq
)] )]
mod button_group; mod button_group;
@ -78,25 +79,7 @@ const MOUSE_EVENT_BUTTONS_FOURTH: u16 = 8;
#[allow(dead_code)] #[allow(dead_code)]
const MOUSE_EVENT_BUTTONS_FIFTH: u16 = 16; const MOUSE_EVENT_BUTTONS_FIFTH: u16 = 16;
#[macro_export] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
macro_rules! if_html {
(let $pat:pat = $cond:expr => $($body:tt)+) => {
if let $pat = $cond {
html!($($body)+)
} else {
html!()
}
};
($cond:expr => $($body:tt)+) => {
if $cond {
html($(body)+)
} else {
html!()
}
};
}
#[derive(Debug, Copy, Clone, PartialEq, Hash)]
pub enum Intent { pub enum Intent {
Primary, Primary,
Success, Success,

View file

@ -7,6 +7,7 @@ use web_sys::HtmlInputElement;
use yew::html::IntoPropValue; use yew::html::IntoPropValue;
use yew::prelude::*; use yew::prelude::*;
#[derive(Debug)]
pub struct NumericInput<T> pub struct NumericInput<T>
where where
T: Add<Output = T> T: Add<Output = T>
@ -208,7 +209,7 @@ where
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NumericInputRangeBounds<T> { pub struct NumericInputRangeBounds<T> {
pub start: Bound<T>, pub start: Bound<T>,
pub end: Bound<T>, pub end: Bound<T>,

View file

@ -1,4 +1,4 @@
use crate::{if_html, Icon, IconName, Intent, Text}; use crate::{Icon, IconName, Intent, Text};
use yew::prelude::*; use yew::prelude::*;
use yew::virtual_dom::AttrValue; use yew::virtual_dom::AttrValue;
@ -41,14 +41,20 @@ pub struct TagProps {
#[function_component(Tag)] #[function_component(Tag)]
pub fn tag(props: &TagProps) -> Html { pub fn tag(props: &TagProps) -> Html {
let icon = if_html!(let Some(icon) = props.icon => <Icon icon={icon} />); let icon = props.icon.map(|icon| {
html! {
<Icon icon={icon} />
}
});
let right_icon = let right_icon = props.right_icon.map(|icon| {
if_html!(let Some(right_icon) = props.right_icon => <Icon icon={right_icon} />); html! {
<Icon icon={icon} />
}
});
let remove_button = if_html! { let remove_button = props.onremove.clone().map(|callback| {
let Some(callback) = props.onremove.clone() => html! {
html!(
<button <button
class={classes!("bp3-tag-remove")} class={classes!("bp3-tag-remove")}
onclick={callback} onclick={callback}
@ -56,8 +62,8 @@ pub fn tag(props: &TagProps) -> Html {
> >
<Icon icon={IconName::SmallCross} /> <Icon icon={IconName::SmallCross} />
</button> </button>
) }
}; });
html! { html! {
<span <span
@ -75,7 +81,7 @@ pub fn tag(props: &TagProps) -> Html {
style={props.style.clone()} style={props.style.clone()}
onclick={props.onclick.clone()} onclick={props.onclick.clone()}
> >
{icon} {icon.unwrap_or_default()}
<Text <Text
class={classes!("bp3-fill")} class={classes!("bp3-fill")}
ellipsize={!props.multiline} ellipsize={!props.multiline}
@ -84,8 +90,8 @@ pub fn tag(props: &TagProps) -> Html {
> >
{props.children.clone()} {props.children.clone()}
</Text> </Text>
{right_icon} {right_icon.unwrap_or_default()}
{remove_button} {remove_button.unwrap_or_default()}
</span> </span>
} }
} }

View file

@ -322,7 +322,7 @@ fn switch(route: &DocMenu) -> Html {
} }
} }
#[derive(PartialEq, Clone, Routable)] #[derive(PartialEq, Eq, Hash, Clone, Copy, Routable)]
pub enum DocMenu { pub enum DocMenu {
#[at("/button-group")] #[at("/button-group")]
ButtonGroup, ButtonGroup,

View file

@ -66,7 +66,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
minimal: !props.minimal, minimal: !props.minimal,
..props ..props
})} })}
@ -74,7 +74,7 @@ crate::build_example_prop_component! {
label={html!("Minimal")} label={html!("Minimal")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps{ onclick={self.update_props(ctx, |props, _| ExampleProps{
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
@ -82,7 +82,7 @@ crate::build_example_prop_component! {
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps{ onclick={self.update_props(ctx, |props, _| ExampleProps{
large: !props.large, large: !props.large,
..props ..props
})} })}
@ -90,7 +90,7 @@ crate::build_example_prop_component! {
label={html!("Large")} label={html!("Large")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
vertical: !props.vertical, vertical: !props.vertical,
..props ..props
})} })}

View file

@ -73,7 +73,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
minimal: !props.minimal, minimal: !props.minimal,
..props ..props
})} })}
@ -81,7 +81,7 @@ crate::build_example_prop_component! {
label={html!("Minimal")} label={html!("Minimal")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
@ -89,7 +89,7 @@ crate::build_example_prop_component! {
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
small: !props.small, small: !props.small,
..props ..props
})} })}
@ -97,7 +97,7 @@ crate::build_example_prop_component! {
label={html!("Small")} label={html!("Small")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
outlined: !props.outlined, outlined: !props.outlined,
..props ..props
})} })}
@ -105,7 +105,7 @@ crate::build_example_prop_component! {
label={html!("Outlined")} label={html!("Outlined")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
loading: !props.loading, loading: !props.loading,
..props ..props
})} })}
@ -113,7 +113,7 @@ crate::build_example_prop_component! {
label={html!("Loading")} label={html!("Loading")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}
@ -121,7 +121,7 @@ crate::build_example_prop_component! {
label={html!("Large")} label={html!("Large")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
active: !props.active, active: !props.active,
..props ..props
})} })}
@ -129,7 +129,7 @@ crate::build_example_prop_component! {
label={html!("Active")} label={html!("Active")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disabled: !props.disabled, disabled: !props.disabled,
..props ..props
})} })}

View file

@ -65,7 +65,7 @@ crate::build_example_prop_component! {
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<div> <div>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
show_icon: !props.show_icon, show_icon: !props.show_icon,
..props ..props
})} })}
@ -73,7 +73,7 @@ crate::build_example_prop_component! {
label={html!("Show/hide icon")} label={html!("Show/hide icon")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
show_title: !props.show_title, show_title: !props.show_title,
..props ..props
})} })}
@ -89,7 +89,7 @@ crate::build_example_prop_component! {
(Some(Intent::Warning), "Warning".to_string()), (Some(Intent::Warning), "Warning".to_string()),
(Some(Intent::Danger), "Danger".to_string()), (Some(Intent::Danger), "Danger".to_string()),
]} ]}
onchange={self.update_props(ctx.props(), |props, intent| ExampleProps { onchange={self.update_props(ctx, |props, intent| ExampleProps {
intent, intent,
..props ..props
})} })}

View file

@ -59,14 +59,12 @@ impl Component for CardDoc {
crate::build_example_prop_component! { crate::build_example_prop_component! {
CardProps for ExampleProps => CardProps for ExampleProps =>
fn view(&self, ctx: &Context<Self>) -> Html { fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();
html! { html! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<div> <div>
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
interactive: !props.interactive, interactive: !props.interactive,
..props ..props
})} })}
@ -83,7 +81,7 @@ crate::build_example_prop_component! {
(Elevation::Level4, "Level 4".to_string()), (Elevation::Level4, "Level 4".to_string()),
]} ]}
value={ctx.props().example_props.elevation} value={ctx.props().example_props.elevation}
onchange={self.update_props(props, |props, elevation| ExampleProps { onchange={self.update_props(ctx, |props, elevation| ExampleProps {
elevation, elevation,
..props ..props
})} })}

View file

@ -64,7 +64,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disabled: !props.disabled, disabled: !props.disabled,
..props ..props
})} })}
@ -72,7 +72,7 @@ crate::build_example_prop_component! {
label={html!("Disabled")} label={html!("Disabled")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
inline: !props.inline, inline: !props.inline,
..props ..props
})} })}
@ -80,7 +80,7 @@ crate::build_example_prop_component! {
label={html!("Inline")} label={html!("Inline")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}

View file

@ -29,7 +29,7 @@ pub fn example(props: &ExampleProps) -> Html {
} }
} }
#[derive(Debug, Clone, Copy, Hash, PartialEq)] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Sorting { pub enum Sorting {
NameAscending, NameAscending,
NameDescending, NameDescending,

View file

@ -64,7 +64,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
@ -72,7 +72,7 @@ crate::build_example_prop_component! {
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
vertical: !props.vertical, vertical: !props.vertical,
..props ..props
})} })}

View file

@ -60,7 +60,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
vertical: !props.vertical vertical: !props.vertical
})} })}
checked={ctx.props().example_props.vertical} checked={ctx.props().example_props.vertical}

View file

@ -100,10 +100,10 @@ macro_rules! build_example_prop_component {
/// re-rendered. /// re-rendered.
fn update_props<T>( fn update_props<T>(
&self, &self,
props: &Self, ctx: &Context<Self>,
updater: impl Fn($prop_component, T) -> $prop_component + 'static, updater: impl Fn($prop_component, T) -> $prop_component + 'static,
) -> Callback<T> { ) -> Callback<T> {
let example_props = props.example_props.clone(); let example_props = ctx.props().example_props.clone();
self.callback self.callback
.clone() .clone()
.reform(move |event| updater(example_props.clone(), event)) .reform(move |event| updater(example_props.clone(), event))

View file

@ -3,10 +3,12 @@ use yewprint::{HtmlSelect, Text};
pub struct Example { pub struct Example {
log_level: LogLevel, log_level: LogLevel,
reset: usize,
} }
#[derive(Clone, PartialEq, Properties)] #[derive(Clone, PartialEq, Properties)]
pub struct ExampleProps { pub struct ExampleProps {
pub reset: usize,
pub minimal: bool, pub minimal: bool,
pub fill: bool, pub fill: bool,
pub disabled: bool, pub disabled: bool,
@ -20,6 +22,7 @@ impl Component for Example {
fn create(_ctx: &Context<Self>) -> Self { fn create(_ctx: &Context<Self>) -> Self {
Example { Example {
log_level: LogLevel::Info, log_level: LogLevel::Info,
reset: 0,
} }
} }
@ -28,6 +31,14 @@ impl Component for Example {
true true
} }
fn changed(&mut self, ctx: &Context<Self>) -> bool {
if self.reset != ctx.props().reset {
self.reset = ctx.props().reset;
self.log_level = LogLevel::Info;
}
true
}
fn view(&self, ctx: &Context<Self>) -> Html { fn view(&self, ctx: &Context<Self>) -> Html {
html! { html! {
<div style="width: 400px; text-align: center;"> <div style="width: 400px; text-align: center;">
@ -44,7 +55,7 @@ impl Component for Example {
fill={ctx.props().fill} fill={ctx.props().fill}
disabled={ctx.props().disabled} disabled={ctx.props().disabled}
large={ctx.props().large} large={ctx.props().large}
value={Some(self.log_level)} value={self.log_level}
onchange={ctx.link().callback(|x| x)} onchange={ctx.link().callback(|x| x)}
title={format!("Selected: {:?}", self.log_level)} title={format!("Selected: {:?}", self.log_level)}
/> />
@ -54,7 +65,7 @@ impl Component for Example {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LogLevel { pub enum LogLevel {
Trace, Trace,
Debug, Debug,

View file

@ -3,7 +3,7 @@ mod example;
use crate::ExampleContainer; use crate::ExampleContainer;
use example::*; use example::*;
use yew::prelude::*; use yew::prelude::*;
use yewprint::{Switch, H1, H5}; use yewprint::{Button, IconName, Switch, H1, H5};
pub struct HtmlSelectDoc { pub struct HtmlSelectDoc {
callback: Callback<ExampleProps>, callback: Callback<ExampleProps>,
@ -18,6 +18,7 @@ impl Component for HtmlSelectDoc {
HtmlSelectDoc { HtmlSelectDoc {
callback: ctx.link().callback(|x| x), callback: ctx.link().callback(|x| x),
state: ExampleProps { state: ExampleProps {
reset: 0,
minimal: false, minimal: false,
fill: false, fill: false,
disabled: false, disabled: false,
@ -67,7 +68,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
minimal: !props.minimal, minimal: !props.minimal,
..props ..props
})} })}
@ -75,7 +76,7 @@ crate::build_example_prop_component! {
label={html!("Minimal")} label={html!("Minimal")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps{ onclick={self.update_props(ctx, |props, _| ExampleProps{
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
@ -83,7 +84,7 @@ crate::build_example_prop_component! {
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disabled: !props.disabled, disabled: !props.disabled,
..props ..props
})} })}
@ -91,13 +92,23 @@ crate::build_example_prop_component! {
label={html!("Disabled")} label={html!("Disabled")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps{ onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}
checked={ctx.props().example_props.large} checked={ctx.props().example_props.large}
label={html!("Large")} label={html!("Large")}
/> />
<H5>{"Example"}</H5>
<Button
icon={IconName::Refresh}
onclick={self.update_props(ctx, |props, _| ExampleProps {
reset: props.reset.wrapping_add(1),
..props
})}
>
{"Reset"}
</Button>
</div> </div>
} }
} }

View file

@ -67,7 +67,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disabled: !props.disabled, disabled: !props.disabled,
..props ..props
})} })}
@ -75,7 +75,7 @@ crate::build_example_prop_component! {
label={html!("Disabled")} label={html!("Disabled")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
@ -83,7 +83,7 @@ crate::build_example_prop_component! {
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}
@ -91,7 +91,7 @@ crate::build_example_prop_component! {
label={html!("Large")} label={html!("Large")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
small: !props.small, small: !props.small,
..props ..props
})} })}
@ -99,7 +99,7 @@ crate::build_example_prop_component! {
label={html!("Small")} label={html!("Small")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
round: !props.round, round: !props.round,
..props ..props
})} })}

View file

@ -1,4 +1,9 @@
#![allow(clippy::redundant_closure, clippy::needless_update, dead_code)] #![allow(
clippy::redundant_closure,
clippy::needless_update,
dead_code,
clippy::derive_partial_eq_without_eq
)]
mod app; mod app;
mod button_group; mod button_group;

View file

@ -69,7 +69,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
@ -77,7 +77,7 @@ crate::build_example_prop_component! {
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disabled: !props.disabled, disabled: !props.disabled,
..props ..props
})} })}
@ -85,7 +85,7 @@ crate::build_example_prop_component! {
label={html!("Disabled")} label={html!("Disabled")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}
@ -93,7 +93,7 @@ crate::build_example_prop_component! {
label={html!("Large")} label={html!("Large")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disable_buttons: !props.disable_buttons, disable_buttons: !props.disable_buttons,
..props ..props
})} })}
@ -101,7 +101,7 @@ crate::build_example_prop_component! {
label={html!("Disable buttons")} label={html!("Disable buttons")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
buttons_on_the_left: !props.buttons_on_the_left, buttons_on_the_left: !props.buttons_on_the_left,
..props ..props
})} })}
@ -109,7 +109,7 @@ crate::build_example_prop_component! {
label={html!("Buttons on the left")} label={html!("Buttons on the left")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
left_icon: !props.left_icon, left_icon: !props.left_icon,
..props ..props
})} })}

View file

@ -11,7 +11,7 @@ pub struct ExampleProps {
pub vertical: bool, pub vertical: bool,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum ExampleMessage { pub enum ExampleMessage {
OpenPanel2, OpenPanel2,
ClosePanel, ClosePanel,

View file

@ -65,7 +65,7 @@ crate::build_example_prop_component! {
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<div> <div>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
stripes: !props.stripes, stripes: !props.stripes,
..props ..props
})} })}
@ -73,7 +73,7 @@ crate::build_example_prop_component! {
label={html!("Stripes")} label={html!("Stripes")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
animate: !props.animate, animate: !props.animate,
..props ..props
})} })}
@ -89,7 +89,7 @@ crate::build_example_prop_component! {
(Some(Intent::Warning), "Warning".to_string()), (Some(Intent::Warning), "Warning".to_string()),
(Some(Intent::Danger), "Danger".to_string()), (Some(Intent::Danger), "Danger".to_string()),
]} ]}
onchange={self.update_props(ctx.props(), |props, intent| ExampleProps { onchange={self.update_props(ctx, |props, intent| ExampleProps {
intent, intent,
..props ..props
})} })}

View file

@ -64,7 +64,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disabled: !props.disabled, disabled: !props.disabled,
..props ..props
})} })}
@ -72,7 +72,7 @@ crate::build_example_prop_component! {
label={html!("Disabled")} label={html!("Disabled")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
inline: !props.inline, inline: !props.inline,
..props ..props
})} })}
@ -80,7 +80,7 @@ crate::build_example_prop_component! {
label={html!("Inline")} label={html!("Inline")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}

View file

@ -103,7 +103,7 @@ impl Component for Example {
(LogLevel::Trace, Some("TRACE".into())), (LogLevel::Trace, Some("TRACE".into())),
]} ]}
intent={ctx.props().intent} intent={ctx.props().intent}
selected={self.log_level.clone()} selected={self.log_level}
onchange={ctx.link().callback(|x| Msg::LogLevelUpdate(x))} onchange={ctx.link().callback(|x| Msg::LogLevelUpdate(x))}
/> />
<Slider<()> <Slider<()>
@ -117,7 +117,7 @@ impl Component for Example {
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LogLevel { pub enum LogLevel {
Trace, Trace,
Debug, Debug,

View file

@ -109,7 +109,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
vertical: !props.vertical, vertical: !props.vertical,
..props ..props
})} })}
@ -126,7 +126,7 @@ crate::build_example_prop_component! {
(Some(Intent::Warning), "Warning".to_string()), (Some(Intent::Warning), "Warning".to_string()),
(Some(Intent::Danger), "Danger".to_string()), (Some(Intent::Danger), "Danger".to_string()),
]} ]}
onchange={self.update_props(ctx.props(), |props, intent| ExampleProps { onchange={self.update_props(ctx, |props, intent| ExampleProps {
intent, intent,
..props ..props
})} })}

View file

@ -74,7 +74,7 @@ crate::build_example_prop_component! {
(Some(Intent::Warning), "Warning".to_string()), (Some(Intent::Warning), "Warning".to_string()),
(Some(Intent::Danger), "Danger".to_string()), (Some(Intent::Danger), "Danger".to_string()),
]} ]}
onchange={self.update_props(ctx.props(), |props, intent| ExampleProps { onchange={self.update_props(ctx, |props, intent| ExampleProps {
intent, intent,
..props ..props
})} })}
@ -98,7 +98,7 @@ crate::build_example_prop_component! {
(90, None), (90, None),
(100, Some("100".into())), (100, Some("100".into())),
]} ]}
onchange={self.update_props(ctx.props(), |props, size| ExampleProps { onchange={self.update_props(ctx, |props, size| ExampleProps {
size, size,
..props ..props
})} })}

View file

@ -66,7 +66,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
disabled: !props.disabled, disabled: !props.disabled,
..props ..props
})} })}
@ -74,7 +74,7 @@ crate::build_example_prop_component! {
label={html!("Disabled")} label={html!("Disabled")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
inline: !props.inline, inline: !props.inline,
..props ..props
})} })}
@ -82,7 +82,7 @@ crate::build_example_prop_component! {
label={html!("Inline")} label={html!("Inline")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}
@ -90,7 +90,7 @@ crate::build_example_prop_component! {
label={html!("Large")} label={html!("Large")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
align_right: !props.align_right, align_right: !props.align_right,
..props ..props
})} })}

View file

@ -127,7 +127,7 @@ impl Component for Example {
} }
} }
#[derive(Clone, Copy, PartialEq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Civilization { pub enum Civilization {
Sumer, Sumer,
Minoan, Minoan,

View file

@ -65,7 +65,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
animate: !props.animate, animate: !props.animate,
..props ..props
})} })}
@ -73,7 +73,7 @@ crate::build_example_prop_component! {
label={html!("Animate indicator")} label={html!("Animate indicator")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
vertical: !props.vertical, vertical: !props.vertical,
..props ..props
})} })}

View file

@ -84,90 +84,88 @@ impl Component for TagDoc {
crate::build_example_prop_component! { crate::build_example_prop_component! {
TagProps for ExampleProps => TagProps for ExampleProps =>
fn view(&self, ctx: &Context<Self>) -> Html { fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();
html! { html! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<div> <div>
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
active: !props.active, active: !props.active,
..props ..props
})} })}
checked={props.example_props.active} checked={ctx.props().example_props.active}
label={html!("Active")} label={html!("Active")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
checked={props.example_props.fill} checked={ctx.props().example_props.fill}
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
interactive: !props.interactive, interactive: !props.interactive,
..props ..props
})} })}
checked={props.example_props.interactive} checked={ctx.props().example_props.interactive}
label={html!("Interactive")} label={html!("Interactive")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}
checked={props.example_props.large} checked={ctx.props().example_props.large}
label={html!("Large")} label={html!("Large")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
minimal: !props.minimal, minimal: !props.minimal,
..props ..props
})} })}
checked={props.example_props.minimal} checked={ctx.props().example_props.minimal}
label={html!("Minimal")} label={html!("Minimal")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
multiline: !props.multiline, multiline: !props.multiline,
..props ..props
})} })}
checked={props.example_props.multiline} checked={ctx.props().example_props.multiline}
label={html!("Multiline")} label={html!("Multiline")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
round: !props.round, round: !props.round,
..props ..props
})} })}
checked={props.example_props.round} checked={ctx.props().example_props.round}
label={html!("Round")} label={html!("Round")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
removable: !props.removable, removable: !props.removable,
..props ..props
})} })}
checked={props.example_props.removable} checked={ctx.props().example_props.removable}
label={html!("Removable")} label={html!("Removable")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
icon: !props.icon, icon: !props.icon,
..props ..props
})} })}
checked={props.example_props.icon} checked={ctx.props().example_props.icon}
label={html!("Icon")} label={html!("Icon")}
/> />
<Switch <Switch
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
right_icon: !props.right_icon, right_icon: !props.right_icon,
..props ..props
})} })}
checked={props.example_props.right_icon} checked={ctx.props().example_props.right_icon}
label={html!("Right icon")} label={html!("Right icon")}
/> />
<p>{"Select intent:"}</p> <p>{"Select intent:"}</p>
@ -182,14 +180,14 @@ crate::build_example_prop_component! {
(Some(Intent::Warning), "Warning".to_string()), (Some(Intent::Warning), "Warning".to_string()),
(Some(Intent::Danger), "Danger".to_string()), (Some(Intent::Danger), "Danger".to_string()),
]} ]}
onchange={self.update_props(props, |props, intent| ExampleProps { onchange={self.update_props(ctx, |props, intent| ExampleProps {
intent, intent,
..props ..props
})} })}
/> />
<Button <Button
icon={IconName::Refresh} icon={IconName::Refresh}
onclick={self.update_props(props, |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
reset_tags: props.reset_tags + 1, reset_tags: props.reset_tags + 1,
..props.clone() ..props.clone()
})} })}

View file

@ -66,7 +66,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
ellipsize: !props.ellipsize, ellipsize: !props.ellipsize,
..props ..props
})} })}
@ -75,7 +75,7 @@ crate::build_example_prop_component! {
/> />
<input <input
class="bp3-input" class="bp3-input"
onchange={self.update_props(ctx.props(), |props, e: Event| { onchange={self.update_props(ctx, |props, e: Event| {
if let Some(input) = e.target_dyn_into::<HtmlInputElement>() { if let Some(input) = e.target_dyn_into::<HtmlInputElement>() {
ExampleProps { ExampleProps {
text: input.value(), text: input.value(),

View file

@ -67,7 +67,7 @@ crate::build_example_prop_component! {
<div> <div>
<H5>{"Props"}</H5> <H5>{"Props"}</H5>
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
fill: !props.fill, fill: !props.fill,
..props ..props
})} })}
@ -75,7 +75,7 @@ crate::build_example_prop_component! {
label={html!("Fill")} label={html!("Fill")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
large: !props.large, large: !props.large,
..props ..props
})} })}
@ -83,7 +83,7 @@ crate::build_example_prop_component! {
label={html!("Large")} label={html!("Large")}
/> />
<Switch <Switch
onclick={self.update_props(ctx.props(), |props, _| ExampleProps { onclick={self.update_props(ctx, |props, _| ExampleProps {
small: !props.small, small: !props.small,
..props ..props
})} })}
@ -98,7 +98,7 @@ crate::build_example_prop_component! {
(Some(Intent::Warning), "Warning".to_string()), (Some(Intent::Warning), "Warning".to_string()),
(Some(Intent::Danger), "Danger".to_string()), (Some(Intent::Danger), "Danger".to_string()),
]} ]}
onchange={self.update_props(ctx.props(), |props, intent| ExampleProps { onchange={self.update_props(ctx, |props, intent| ExampleProps {
intent, intent,
..props ..props
})} })}