Co-authored-by: Cecile Tonglet <cecile.tonglet@cecton.com>
This commit is contained in:
Yohan Boogaert 2021-05-28 11:33:03 +02:00 committed by GitHub
parent 1a2594049c
commit 357e0fefde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 379 additions and 0 deletions

View file

@ -10,6 +10,7 @@ use crate::icon::*;
use crate::input_group::*; use crate::input_group::*;
use crate::menu::*; use crate::menu::*;
use crate::progressbar::*; use crate::progressbar::*;
use crate::radio::*;
use crate::slider::*; use crate::slider::*;
use crate::spinner::*; use crate::spinner::*;
use crate::switch::*; use crate::switch::*;
@ -185,6 +186,12 @@ impl Component for App {
onclick=self.link onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::ProgressBar)) .callback(|_| Msg::GoToMenu(DocMenu::ProgressBar))
/> />
<MenuItem
text={html!("Radio")}
href=Cow::Borrowed("#radio")
onclick=self.link
.callback(|_| Msg::GoToMenu(DocMenu::Radio))
/>
<MenuItem <MenuItem
text={html!("Slider")} text={html!("Slider")}
href=Cow::Borrowed("#slider") href=Cow::Borrowed("#slider")
@ -256,6 +263,7 @@ impl Component for App {
DocMenu::InputGroup => html!(<InputGroupDoc />), DocMenu::InputGroup => html!(<InputGroupDoc />),
DocMenu::Menu => html!(<MenuDoc />), DocMenu::Menu => html!(<MenuDoc />),
DocMenu::ProgressBar => html!(<ProgressBarDoc />), DocMenu::ProgressBar => html!(<ProgressBarDoc />),
DocMenu::Radio => html!(<RadioDoc />),
DocMenu::Slider => html!(<SliderDoc />), DocMenu::Slider => html!(<SliderDoc />),
DocMenu::Spinner => html!(<SpinnerDoc />), DocMenu::Spinner => html!(<SpinnerDoc />),
DocMenu::Switch => html!(<SwitchDoc />), DocMenu::Switch => html!(<SwitchDoc />),
@ -300,6 +308,8 @@ pub enum DocMenu {
Menu, Menu,
#[to = "/#progress-bar"] #[to = "/#progress-bar"]
ProgressBar, ProgressBar,
#[to = "/#radio"]
Radio,
#[to = "/#slider"] #[to = "/#slider"]
Slider, Slider,
#[to = "/#spinner"] #[to = "/#spinner"]

View file

@ -14,6 +14,7 @@ mod icon;
mod input_group; mod input_group;
mod menu; mod menu;
mod progressbar; mod progressbar;
mod radio;
mod slider; mod slider;
mod spinner; mod spinner;
mod switch; mod switch;

View file

@ -0,0 +1,99 @@
use yew::prelude::*;
use yewprint::{Label, Radio, RadioGroup};
pub struct Example {
props: ExampleProps,
link: ComponentLink<Self>,
selected_value: Lunch,
}
#[derive(Clone, PartialEq, Properties)]
pub struct ExampleProps {
pub disabled: bool,
pub inline: bool,
pub large: bool,
}
pub enum Msg {
ValueUpdate(Lunch),
}
impl Component for Example {
type Message = Msg;
type Properties = ExampleProps;
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
Example {
props,
selected_value: Lunch::Salad,
link,
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::ValueUpdate(value) => {
self.selected_value = value;
true
}
}
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> Html {
html! {
<>
<div>
<Radio
label=html!("Blue pill")
inline=self.props.inline
disabled=self.props.disabled
large=self.props.large
name="group".to_string()
/>
<Radio
label=html!("Red pill")
inline=self.props.inline
disabled=self.props.disabled
large=self.props.large
name="group".to_string()
/>
</div>
<div>
<RadioGroup<Lunch>
label=Some(html!(
<Label>
{"Determine Lunch"}
</Label>
))
options=vec![
(Lunch::Soup, "Soup".to_string()),
(Lunch::Salad, "Salad".to_string()),
(Lunch::Sandwich, "Sandwich".to_string()),
]
value=self.selected_value
onchange=self.link.callback(|v| Msg::ValueUpdate(v))
inline=self.props.inline
disabled=self.props.disabled
large=self.props.large
/>
</div>
</>
}
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq)]
pub enum Lunch {
Soup,
Salad,
Sandwich,
}

View file

@ -0,0 +1,96 @@
mod example;
use crate::ExampleContainer;
use example::*;
use yew::prelude::*;
use yewprint::{Switch, H1, H5};
pub struct RadioDoc {
callback: Callback<ExampleProps>,
state: ExampleProps,
}
impl Component for RadioDoc {
type Message = ExampleProps;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
RadioDoc {
callback: link.callback(|x| x),
state: ExampleProps {
disabled: false,
inline: false,
large: false,
},
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
self.state = msg;
true
}
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
true
}
fn view(&self) -> Html {
let example_props = self.state.clone();
let source = crate::include_raw_html!(
concat!(env!("OUT_DIR"), "/", file!(), ".html"),
"bp3-code-block"
);
html! {
<div>
<H1 class=classes!("docs-title")>{"Radio"}</H1>
<ExampleContainer
source=source
props=Some(html! {
<RadioProps
callback={self.callback.clone()}
props=example_props.clone()
/>
})
>
<Example with example_props />
</ExampleContainer>
</div>
}
}
}
crate::build_example_prop_component! {
RadioProps for ExampleProps =>
fn view(&self) -> Html {
html! {
<div>
<H5>{"Props"}</H5>
<Switch
onclick=self.update_props(|props, _| ExampleProps {
disabled: !props.disabled,
..props
})
checked=self.props.disabled
label=html!("Disabled")
/>
<Switch
onclick=self.update_props(|props, _| ExampleProps {
inline: !props.inline,
..props
})
checked=self.props.inline
label=html!("Inline")
/>
<Switch
onclick=self.update_props(|props, _| ExampleProps {
large: !props.large,
..props
})
checked=self.props.large
label=html!("Large")
/>
</div>
}
}
}

View file

@ -17,6 +17,8 @@ mod icon;
mod input_group; mod input_group;
mod menu; mod menu;
mod progressbar; mod progressbar;
mod radio;
mod radio_group;
mod slider; mod slider;
mod spinner; mod spinner;
mod switch; mod switch;
@ -41,6 +43,8 @@ pub use id_tree;
pub use input_group::*; pub use input_group::*;
pub use menu::*; pub use menu::*;
pub use progressbar::*; pub use progressbar::*;
pub use radio::*;
pub use radio_group::*;
pub use slider::*; pub use slider::*;
pub use spinner::*; pub use spinner::*;
pub use switch::*; pub use switch::*;

75
yewprint/src/radio.rs Normal file
View file

@ -0,0 +1,75 @@
use yew::prelude::*;
pub struct Radio {
props: RadioProps,
}
#[derive(Clone, PartialEq, Properties)]
pub struct RadioProps {
#[prop_or_default]
pub disabled: bool,
#[prop_or_default]
pub inline: bool,
#[prop_or_default]
pub large: bool,
#[prop_or_default]
pub checked: Option<bool>,
#[prop_or_default]
pub name: Option<String>,
#[prop_or_default]
pub onchange: Option<Callback<ChangeData>>,
#[prop_or_default]
pub label: yew::virtual_dom::VNode,
#[prop_or_default]
pub value: Option<String>,
}
impl Component for Radio {
type Message = ();
type Properties = RadioProps;
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> Html {
html! {
<label
class=classes!(
"bp3-control",
"bp3-radio",
self.props.disabled.then(|| "bp3-disabled"),
self.props.inline.then(|| "bp3-inline"),
self.props.large.then(|| "bp3-large"),
)
>
<input
type="radio"
onchange={self.props.onchange.clone().unwrap_or_default()}
disabled=self.props.disabled
value={self.props.value.clone().unwrap_or_default()}
checked=self.props.checked.unwrap_or(false)
name={self.props.name.clone().unwrap_or_default()}
/>
<span
class=classes!("bp3-control-indicator")
>
</span>
{self.props.label.clone()}
</label>
}
}
}

View file

@ -0,0 +1,94 @@
use crate::Radio;
use yew::prelude::*;
pub struct RadioGroup<T: Clone + PartialEq + 'static> {
props: RadioGroupProps<T>,
}
#[derive(Clone, PartialEq, Properties)]
pub struct RadioGroupProps<T: Clone + PartialEq + 'static> {
#[prop_or_default]
pub label: Option<yew::virtual_dom::VNode>,
#[prop_or_default]
pub disabled: bool,
#[prop_or_default]
pub inline: bool,
#[prop_or_default]
pub large: bool,
pub options: Vec<(T, String)>,
#[prop_or_default]
pub value: Option<T>,
#[prop_or_default]
pub onchange: Callback<T>,
#[prop_or_default]
pub class: Classes,
}
impl<T: Clone + PartialEq + 'static> Component for RadioGroup<T> {
type Message = ();
type Properties = RadioGroupProps<T>;
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
fn view(&self) -> Html {
let option_children = self
.props
.options
.iter()
.map(|(value, label)| {
let checked = self
.props
.value
.as_ref()
.map(|x| value == x)
.unwrap_or_default();
let value = value.clone();
html! {
<Radio
value="".to_string()
label=html!(label)
checked=checked
onchange=self.props.onchange.reform(move |_| value.clone())
inline=self.props.inline
disabled=self.props.disabled
large=self.props.large
/>
}
})
.collect::<Html>();
html! {
<div
class=classes!(
"bp3-radio-group",
self.props.class.clone(),
)
>
{
if let Some(label) = self.props.label.clone() {
label
} else {
html!()
}
}
{option_children}
</div>
}
}
}