use derive_more::Display;
use yew::events::{Event, FocusEvent, MouseEvent};
use yew::prelude::*;
use yewtil::NeqAssign;
#[derive(Clone, Debug, Properties, PartialEq)]
pub struct ButtonsProps {
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub classes: Option<String>,
#[prop_or_default]
pub size: Option<ButtonGroupSize>,
}
pub struct Buttons {
props: ButtonsProps,
}
impl Component for Buttons {
type Message = ();
type Properties = ButtonsProps;
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props.neq_assign(props)
}
fn view(&self) -> Html {
let mut classes = Classes::from("buttons");
if let Some(extra) = &self.props.classes {
classes = classes.extend(extra);
}
if let Some(size) = &self.props.size {
classes.push(&size.to_string());
}
html! {
<div class=classes>
{self.props.children.clone()}
</div>
}
}
}
#[derive(Clone, Debug, Display, PartialEq)]
#[display(fmt = "are-{}")]
pub enum ButtonGroupSize {
#[display(fmt = "small")]
Small,
#[display(fmt = "medium")]
Medium,
#[display(fmt = "large")]
Large,
}
#[derive(Clone, Debug, Properties, PartialEq)]
pub struct ButtonProps {
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub classes: Option<String>,
#[prop_or_else(Callback::noop)]
pub onclick: Callback<MouseEvent>,
#[prop_or_default]
pub loading: bool,
#[prop_or_default]
pub r#static: bool,
#[prop_or_default]
pub disabled: bool,
}
pub struct Button {
props: ButtonProps,
}
impl Component for Button {
type Message = ();
type Properties = ButtonProps;
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props.neq_assign(props)
}
fn view(&self) -> Html {
let mut classes = Classes::from("button");
if let Some(extra) = &self.props.classes {
classes = classes.extend(extra);
}
if self.props.loading {
classes.push("is-loading")
}
if self.props.r#static {
classes.push("is-static")
}
if self.props.disabled {
classes.push("is-disabled")
}
html! {
<button class=classes onclick=self.props.onclick.clone()>
{self.props.children.clone()}
</button>
}
}
}
#[cfg(feature = "router")]
mod router {
use super::*;
use yew_router::components::{RouterAnchor, RouterButton as RouterBtn};
use yew_router::{RouterState, Switch};
#[derive(Clone, Properties, PartialEq)]
pub struct ButtonRouterProps<SW: Switch + Clone + PartialEq + 'static> {
pub route: SW,
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub classes: Option<String>,
#[prop_or_default]
pub loading: bool,
#[prop_or_default]
pub r#static: bool,
#[prop_or_default]
pub disabled: bool,
}
pub struct ButtonRouter<SW: Switch + Clone + PartialEq + 'static, STATE: RouterState = ()> {
props: ButtonRouterProps<SW>,
marker: std::marker::PhantomData<STATE>,
}
impl<SW: Switch + Clone + PartialEq + 'static, STATE: RouterState> Component for ButtonRouter<SW, STATE> {
type Message = ();
type Properties = ButtonRouterProps<SW>;
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
Self {
props,
marker: std::marker::PhantomData,
}
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props.neq_assign(props)
}
#[allow(deprecated)]
fn view(&self) -> Html {
let mut classes = Classes::from(&self.props.classes);
if !classes.contains("button") {
classes.push("button")
}
if self.props.loading {
classes.push("is-loading");
}
html! {
<RouterBtn<SW, STATE>
route=self.props.route.clone()
disabled=self.props.disabled
classes=classes.to_string()
children=self.props.children.clone()
/>
}
}
}
pub struct ButtonAnchorRouter<SW: Switch + Clone + PartialEq + 'static, STATE: RouterState = ()> {
props: ButtonRouterProps<SW>,
marker: std::marker::PhantomData<STATE>,
}
impl<SW: Switch + Clone + PartialEq + 'static, STATE: RouterState> Component for ButtonAnchorRouter<SW, STATE> {
type Message = ();
type Properties = ButtonRouterProps<SW>;
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
Self {
props,
marker: std::marker::PhantomData,
}
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props.neq_assign(props)
}
#[allow(deprecated)]
fn view(&self) -> Html {
let mut classes = Classes::from(&self.props.classes);
if !classes.contains("button") {
classes.push("button")
}
if self.props.loading {
classes.push("is-loading");
}
html! {
<RouterAnchor<SW, STATE>
route=self.props.route.clone()
disabled=self.props.disabled
classes=classes.to_string()
children=self.props.children.clone()
/>
}
}
}
}
#[cfg(feature = "router")]
pub use router::{ButtonAnchorRouter, ButtonRouter, ButtonRouterProps};
#[derive(Clone, Debug, Properties, PartialEq)]
pub struct ButtonAnchorProps {
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub classes: Option<String>,
#[prop_or_default]
pub href: String,
#[prop_or_else(Callback::noop)]
pub onclick: Callback<MouseEvent>,
#[prop_or_default]
pub loading: bool,
#[prop_or_default]
pub r#static: bool,
#[prop_or_default]
pub disabled: bool,
}
pub struct ButtonAnchor {
props: ButtonAnchorProps,
}
impl Component for ButtonAnchor {
type Message = ();
type Properties = ButtonAnchorProps;
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props.neq_assign(props)
}
fn view(&self) -> Html {
let mut classes = Classes::from("button");
if let Some(extra) = &self.props.classes {
classes = classes.extend(extra);
}
if self.props.loading {
classes.push("is-loading")
}
if self.props.r#static {
classes.push("is-static")
}
if self.props.disabled {
classes.push("is-disabled")
}
html! {
<a class=classes onclick=self.props.onclick.clone() href=self.props.href.clone()>
{self.props.children.clone()}
</a>
}
}
}
#[derive(Clone, Debug, Properties, PartialEq)]
pub struct ButtonInputSubmitProps {
#[prop_or_default]
pub classes: Option<String>,
#[prop_or_else(Callback::noop)]
pub onsubmit: Callback<FocusEvent>,
#[prop_or_default]
pub loading: bool,
#[prop_or_default]
pub r#static: bool,
#[prop_or_default]
pub disabled: bool,
}
pub struct ButtonInputSubmit {
props: ButtonInputSubmitProps,
}
impl Component for ButtonInputSubmit {
type Message = ();
type Properties = ButtonInputSubmitProps;
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props.neq_assign(props)
}
fn view(&self) -> Html {
let mut classes = Classes::from("button");
if let Some(extra) = &self.props.classes {
classes = classes.extend(extra);
}
if self.props.loading {
classes.push("is-loading")
}
if self.props.r#static {
classes.push("is-static")
}
if self.props.disabled {
classes.push("is-disabled")
}
html! {
<input type="submit" class=classes onsubmit=self.props.onsubmit.clone()/>
}
}
}
#[derive(Clone, Debug, Properties, PartialEq)]
pub struct ButtonInputResetProps {
#[prop_or_default]
pub classes: Option<String>,
#[prop_or_else(Callback::noop)]
pub onreset: Callback<Event>,
#[prop_or_default]
pub loading: bool,
#[prop_or_default]
pub r#static: bool,
#[prop_or_default]
pub disabled: bool,
}
pub struct ButtonInputReset {
props: ButtonInputResetProps,
}
impl Component for ButtonInputReset {
type Message = ();
type Properties = ButtonInputResetProps;
fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
Self { props }
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
false
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props.neq_assign(props)
}
fn view(&self) -> Html {
let mut classes = Classes::from("button");
if let Some(extra) = &self.props.classes {
classes = classes.extend(extra);
}
if self.props.loading {
classes.push("is-loading")
}
if self.props.r#static {
classes.push("is-static")
}
if self.props.disabled {
classes.push("is-disabled")
}
html! {
<input type="reset" class=classes onreset=self.props.onreset.clone()/>
}
}
}