feat: change checkbox prop

This commit is contained in:
luoxiao 2023-10-07 15:43:39 +08:00
parent 74a5a3b7b0
commit e98a649154
6 changed files with 70 additions and 36 deletions

View file

@ -19,9 +19,11 @@ pub fn CheckboxPage() -> impl IntoView {
<DemoCode slot html=highlight_str!(r#" <DemoCode slot html=highlight_str!(r#"
let checked = create_rw_signal(false); let checked = create_rw_signal(false);
<Checkbox checked> view! {
"Click" <Checkbox checked>
</Checkbox> "Click"
</Checkbox>
}
"#, "rust")> "#, "rust")>
"" ""
</DemoCode> </DemoCode>
@ -29,9 +31,9 @@ pub fn CheckboxPage() -> impl IntoView {
<h3>"group"</h3> <h3>"group"</h3>
<Demo> <Demo>
<CheckboxGroup value> <CheckboxGroup value>
<CheckboxItem label="apple" value="a" /> <CheckboxItem label="apple" key="a" />
<CheckboxItem label="b" value="b" /> <CheckboxItem label="b" key="b" />
<CheckboxItem label="c" value="c" /> <CheckboxItem label="c" key="c" />
</CheckboxGroup> </CheckboxGroup>
<div style="margin-top: 1rem"> <div style="margin-top: 1rem">
"value: " { move || format!("{:?}", value.get()) } "value: " { move || format!("{:?}", value.get()) }
@ -39,11 +41,13 @@ pub fn CheckboxPage() -> impl IntoView {
<DemoCode slot html=highlight_str!(r#" <DemoCode slot html=highlight_str!(r#"
let value = create_rw_signal(HashSet::new()); let value = create_rw_signal(HashSet::new());
<CheckboxGroup value> view! {
<CheckboxItem label="apple" value="a" /> <CheckboxGroup value>
<CheckboxItem label="b" value="b" /> <CheckboxItem label="apple" key="a" />
<CheckboxItem label="c" value="c" /> <CheckboxItem label="b" key="b" />
</CheckboxGroup> <CheckboxItem label="c" key="c" />
</CheckboxGroup>
}
"#, "rust")> "#, "rust")>
"" ""
</DemoCode> </DemoCode>

View file

@ -1,12 +1,13 @@
use crate::utils::maybe_rw_signal::MaybeRwSignal;
use leptos::*; use leptos::*;
use std::collections::HashSet; use std::collections::HashSet;
#[component] #[component]
pub fn CheckboxGroup( pub fn CheckboxGroup(
#[prop(into)] value: RwSignal<HashSet<String>>, #[prop(optional, into)] value: MaybeRwSignal<HashSet<String>>,
children: Children, children: Children,
) -> impl IntoView { ) -> impl IntoView {
let injection_key = CheckboxGroupInjectionKey::new(value); let injection_key = CheckboxGroupInjectionKey::new(value.into());
provide_context(injection_key); provide_context(injection_key);
children() children()

View file

@ -1,28 +1,36 @@
use crate::checkbox::{checkbox_group::use_checkbox_group, Checkbox}; use crate::{
checkbox::{checkbox_group::use_checkbox_group, Checkbox},
SignalWatch,
};
use leptos::*; use leptos::*;
#[component] #[component]
pub fn CheckboxItem(#[prop(into)] label: String, #[prop(into)] value: String) -> impl IntoView { pub fn CheckboxItem(
#[prop(optional, into)] label: Option<String>,
#[prop(into)] key: String,
) -> impl IntoView {
let checkbox_group = use_checkbox_group(); let checkbox_group = use_checkbox_group();
let checked = checkbox_group let checked = checkbox_group
.value .value
.with_untracked(|checkbox_group| checkbox_group.contains(&value)); .with_untracked(|checkbox_group| checkbox_group.contains(&key));
let checked = create_rw_signal(checked); let checked = create_rw_signal(checked);
let item_value = store_value(value); let item_key = store_value(key);
_ = watch( _ = checked.watch(move |checked| {
move || checked.get(), checkbox_group.value.update(move |checkbox_group| {
move |checked, _prev, _| { if *checked {
checkbox_group.value.update(move |checkbox_group| { checkbox_group.insert(item_key.get_value());
if *checked { } else {
checkbox_group.insert(item_value.get_value()); checkbox_group.remove(&item_key.get_value());
} else { }
checkbox_group.remove(&item_value.get_value()); });
} });
});
}, let label = if let Some(label) = label {
false, label
); } else {
item_key.get_value()
};
view! { view! {
<Checkbox checked> <Checkbox checked>

View file

@ -1,7 +1,13 @@
mod checkbox_group; mod checkbox_group;
mod checkbox_item; mod checkbox_item;
use crate::{components::*, icon::*, theme::use_theme, utils::mount_style::mount_style, Theme}; use crate::{
components::*,
icon::*,
theme::use_theme,
utils::{maybe_rw_signal::MaybeRwSignal, mount_style::mount_style},
Theme,
};
pub use checkbox_group::CheckboxGroup; pub use checkbox_group::CheckboxGroup;
pub use checkbox_item::CheckboxItem; pub use checkbox_item::CheckboxItem;
use icondata::AiIcon; use icondata::AiIcon;
@ -9,7 +15,10 @@ use leptos::*;
use stylers::style_sheet_str; use stylers::style_sheet_str;
#[component] #[component]
pub fn Checkbox(#[prop(into)] checked: RwSignal<bool>, children: Children) -> impl IntoView { pub fn Checkbox(
#[prop(optional, into)] checked: MaybeRwSignal<bool>,
children: Children,
) -> impl IntoView {
let theme = use_theme(Theme::light); let theme = use_theme(Theme::light);
let class_name = mount_style("checkbox", || { let class_name = mount_style("checkbox", || {
style_sheet_str!("./src/checkbox/checkbox.css") style_sheet_str!("./src/checkbox/checkbox.css")
@ -23,12 +32,12 @@ pub fn Checkbox(#[prop(into)] checked: RwSignal<bool>, children: Children) -> im
css_vars css_vars
}); });
view! { class=class_name, view! {class=class_name,
<div class:melt-checkbox=true class=("melt-checkbox--checked", move || checked.get()) style=move || css_vars.get() <div class:melt-checkbox=true class=("melt-checkbox--checked", move || checked.get()) style=move || css_vars.get()
on:click=move |_| checked.set(!checked.get_untracked())> on:click=move |_| checked.set(!checked.get_untracked())>
<input class="melt-checkbox__input" type="checkbox" /> <input class="melt-checkbox__input" type="checkbox" />
<div class="melt-checkbox__dot"> <div class="melt-checkbox__dot">
<If cond=checked> <If cond=checked.clone_into()>
<Then slot> <Then slot>
<Icon icon=Icon::from(AiIcon::AiCheckOutlined) style="color: white"/> <Icon icon=Icon::from(AiIcon::AiCheckOutlined) style="color: white"/>
</Then> </Then>

View file

@ -33,10 +33,10 @@ pub fn Tabs(active_key: RwSignal<&'static str>, children: Children) -> impl Into
}); });
let label_list_ref = create_node_ref::<html::Div>(); let label_list_ref = create_node_ref::<html::Div>();
view! { class=class_name, view! {class=class_name,
<div class="melt-tabs" style=move || css_vars.get()> <div class="melt-tabs" style=move || css_vars.get()>
<div class="melt-tabs__label-list" ref=label_list_ref> <div class="melt-tabs__label-list" ref=label_list_ref>
<For each=move || tab_options_vec.get() key=move |v| v.key.clone() children=move | options| { <For each=move || tab_options_vec.get() key=move |v| v.key children=move | options| {
let label_ref = create_node_ref::<html::Span>(); let label_ref = create_node_ref::<html::Span>();
create_effect( move |_| { create_effect( move |_| {
let Some(label) = label_ref.get() else { let Some(label) = label_ref.get() else {

View file

@ -3,6 +3,12 @@ use std::ops::Deref;
pub struct MaybeRwSignal<T: Default + 'static>(RwSignal<T>); pub struct MaybeRwSignal<T: Default + 'static>(RwSignal<T>);
impl<T: Default> MaybeRwSignal<T> {
pub fn clone_into(&self) -> RwSignal<T> {
self.0.clone()
}
}
impl<T: Default> Default for MaybeRwSignal<T> { impl<T: Default> Default for MaybeRwSignal<T> {
fn default() -> Self { fn default() -> Self {
Self(RwSignal::new(Default::default())) Self(RwSignal::new(Default::default()))
@ -30,3 +36,9 @@ impl<T: Default> From<RwSignal<T>> for MaybeRwSignal<T> {
Self(value) Self(value)
} }
} }
impl<T: Default> From<MaybeRwSignal<T>> for RwSignal<T> {
fn from(value: MaybeRwSignal<T>) -> Self {
value.0
}
}