feat: Button icon property supports the signal (#132)

This commit is contained in:
luoxiaozero 2024-03-07 15:17:26 +08:00 committed by GitHub
parent c1a9f84c9e
commit 9789d4281f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 144 additions and 22 deletions

View file

@ -27,21 +27,51 @@ view! {
### Icon ### Icon
```rust demo ```rust demo
let icon = create_rw_signal(Some(icondata::AiCloseOutlined));
let on_click = move |_| {
icon.update(|icon| {
*icon = match icon {
Some(data) => {
if *data == icondata::AiCloseOutlined {
icondata::AiCheckOutlined
} else {
icondata::AiCloseOutlined
}
}
None => icondata::AiCloseOutlined
}.into();
});
};
view! { view! {
<Space> <Space vertical=true>
<Button color=ButtonColor::Error icon=icondata::AiCloseOutlined> <Space>
"Error Color Icon" <Button icon on_click>
</Button> "Change icon"
<Button </Button>
color=ButtonColor::Error <Button icon on_click=move |_| icon.set(None)>
icon=icondata::AiCloseOutlined "Clear icon"
round=true </Button>
/> </Space>
<Button <Space>
color=ButtonColor::Error <Button color=ButtonColor::Error icon=icondata::AiCloseOutlined>
icon=icondata::AiCloseOutlined "Error Color Icon"
circle=true </Button>
/> <Button color=ButtonColor::Error icon=icondata::AiCloseOutlined>
"Error Color Icon"
</Button>
<Button
color=ButtonColor::Error
icon=icondata::AiCloseOutlined
round=true
/>
<Button
color=ButtonColor::Error
icon=icondata::AiCloseOutlined
circle=true
/>
</Space>
</Space> </Space>
} }
``` ```
@ -135,7 +165,7 @@ view! {
| color | `MaybeSignal<ButtonColor>` | `ButtonColor::Primary` | Button's color. | | color | `MaybeSignal<ButtonColor>` | `ButtonColor::Primary` | Button's color. |
| round | `MaybeSignal<bool>` | `false` | Whether the button shows rounded corners. | | round | `MaybeSignal<bool>` | `false` | Whether the button shows rounded corners. |
| circle | `MaybeSignal<bool>` | `false` | Whether the button is round. | | circle | `MaybeSignal<bool>` | `false` | Whether the button is round. |
| icon | `Option<Icon>` | `None` | The icon of the button. | | icon | `OptionalMaybeSignal<icondata_core::Icon>` | `None` | The icon of the button. |
| loading | `MaybeSignal<bool>` | `false` | Whether the button shows the loading status. | | loading | `MaybeSignal<bool>` | `false` | Whether the button shows the loading status. |
| disabled | `MaybeSignal<bool>` | `false` | Whether the button is disabled. | | disabled | `MaybeSignal<bool>` | `false` | Whether the button is disabled. |
| size | `MaybeSignal<ButtonSize>` | `ButtonSize::Medium` | Button size. | | size | `MaybeSignal<ButtonSize>` | `ButtonSize::Medium` | Button size. |

View file

@ -5,7 +5,7 @@ use crate::{
components::{OptionComp, Wave, WaveRef}, components::{OptionComp, Wave, WaveRef},
icon::Icon, icon::Icon,
theme::*, theme::*,
utils::{class_list::class_list, mount_style, ComponentRef, OptionalProp}, utils::{class_list::class_list, mount_style, ComponentRef, OptionalMaybeSignal, OptionalProp},
}; };
pub use button_group::ButtonGroup; pub use button_group::ButtonGroup;
use leptos::*; use leptos::*;
@ -104,7 +104,7 @@ pub fn Button(
#[prop(optional, into)] size: MaybeSignal<ButtonSize>, #[prop(optional, into)] size: MaybeSignal<ButtonSize>,
#[prop(optional, into)] round: MaybeSignal<bool>, #[prop(optional, into)] round: MaybeSignal<bool>,
#[prop(optional, into)] circle: MaybeSignal<bool>, #[prop(optional, into)] circle: MaybeSignal<bool>,
#[prop(optional, into)] icon: Option<icondata_core::Icon>, #[prop(optional, into)] icon: OptionalMaybeSignal<icondata_core::Icon>,
#[prop(optional, into)] loading: MaybeSignal<bool>, #[prop(optional, into)] loading: MaybeSignal<bool>,
#[prop(optional, into)] disabled: MaybeSignal<bool>, #[prop(optional, into)] disabled: MaybeSignal<bool>,
#[prop(optional, into)] on_click: Option<Callback<ev::MouseEvent>>, #[prop(optional, into)] on_click: Option<Callback<ev::MouseEvent>>,
@ -248,12 +248,17 @@ pub fn Button(
"animation: thawLoadingCircle 1s infinite linear;{icon_style}", "animation: thawLoadingCircle 1s infinite linear;{icon_style}",
) )
/> />
} }.into_view()
.into()
} else if let Some(icon) = icon {
view! { <Icon icon=icon style=icon_style/> }.into()
} else { } else {
None (move || {
let icon = icon.get();
view! {
<OptionComp value=icon let:icon>
<Icon icon=icon style=icon_style/>
</OptionComp>
}
}).into_view()
} }
}} }}

View file

@ -4,6 +4,7 @@ mod component_ref;
mod event_listener; mod event_listener;
mod model; mod model;
mod mount_style; mod mount_style;
mod optional_maybe_signal;
mod optional_prop; mod optional_prop;
mod signal; mod signal;
mod stored_maybe_signal; mod stored_maybe_signal;
@ -16,6 +17,7 @@ pub use component_ref::{create_component_ref, ComponentRef};
pub(crate) use event_listener::*; pub(crate) use event_listener::*;
pub(crate) use model::Model; pub(crate) use model::Model;
pub(crate) use mount_style::mount_style; pub(crate) use mount_style::mount_style;
pub(crate) use optional_maybe_signal::OptionalMaybeSignal;
pub(crate) use optional_prop::OptionalProp; pub(crate) use optional_prop::OptionalProp;
pub use signal::SignalWatch; pub use signal::SignalWatch;
pub(crate) use stored_maybe_signal::*; pub(crate) use stored_maybe_signal::*;

View file

@ -0,0 +1,85 @@
use leptos::*;
use std::ops::Deref;
pub struct OptionalMaybeSignal<T: 'static>(MaybeSignal<Option<T>>);
impl<T> Default for OptionalMaybeSignal<T> {
fn default() -> Self {
Self(MaybeSignal::Static(None))
}
}
impl<T: Copy> Copy for OptionalMaybeSignal<T> {}
impl<T: Clone> Clone for OptionalMaybeSignal<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T> Deref for OptionalMaybeSignal<T> {
type Target = MaybeSignal<Option<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<T> for OptionalMaybeSignal<T> {
fn from(value: T) -> Self {
Self(MaybeSignal::Static(Some(value)))
}
}
impl<T> From<Option<T>> for OptionalMaybeSignal<T> {
fn from(value: Option<T>) -> Self {
Self(MaybeSignal::Static(value))
}
}
impl<T> From<ReadSignal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: ReadSignal<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value.into()))
}
}
impl<T> From<RwSignal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: RwSignal<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value.into()))
}
}
impl<T> From<Memo<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: Memo<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value.into()))
}
}
impl<T> From<Signal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: Signal<Option<T>>) -> Self {
Self(MaybeSignal::Dynamic(value))
}
}
impl<T> From<MaybeSignal<Option<T>>> for OptionalMaybeSignal<T> {
fn from(value: MaybeSignal<Option<T>>) -> Self {
Self(value)
}
}
#[cfg(test)]
mod test {
use super::OptionalMaybeSignal;
use leptos::{create_runtime, MaybeSignal};
#[test]
fn into() {
let runtime = create_runtime();
let _: MaybeSignal<i32> = 12.into();
let _: OptionalMaybeSignal<i32> = Some(12).into();
let _: OptionalMaybeSignal<i32> = MaybeSignal::Static(Some(12)).into();
runtime.dispose();
}
}