mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
feat: checkbox checked
This commit is contained in:
parent
ec351e7ba1
commit
be91dcbf6a
5 changed files with 60 additions and 33 deletions
|
@ -1,10 +1,10 @@
|
||||||
# Checkbox
|
# Checkbox
|
||||||
|
|
||||||
```rust demo
|
```rust demo
|
||||||
let value = create_rw_signal(false);
|
let checked = RwSignal::new(false);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Checkbox value>"Click"</Checkbox>
|
<Checkbox checked>"Click"</Checkbox>
|
||||||
<Checkbox />
|
<Checkbox />
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -14,13 +14,13 @@ view! {
|
||||||
```rust demo
|
```rust demo
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
let value = create_rw_signal(HashSet::new());
|
let value = RwSignal::new(HashSet::new());
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<CheckboxGroup value>
|
<CheckboxGroup value>
|
||||||
<CheckboxItem label="apple" key="a"/>
|
<CheckboxItem label="apple" value="a"/>
|
||||||
<CheckboxItem label="b" key="b"/>
|
<CheckboxItem label="b" value="b"/>
|
||||||
<CheckboxItem label="c" key="c"/>
|
<CheckboxItem label="c" value="c"/>
|
||||||
</CheckboxGroup>
|
</CheckboxGroup>
|
||||||
<div style="margin-top: 1rem">"value: " {move || format!("{:?}", value.get())}</div>
|
<div style="margin-top: 1rem">"value: " {move || format!("{:?}", value.get())}</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,4 +106,5 @@
|
||||||
font-family: var(--fontFamilyBase);
|
font-family: var(--fontFamilyBase);
|
||||||
font-size: var(--fontSizeBase300);
|
font-size: var(--fontSizeBase300);
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
cursor: inherit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,20 @@ pub fn CheckboxGroup(
|
||||||
#[prop(optional, into)] value: Model<HashSet<String>>,
|
#[prop(optional, into)] value: Model<HashSet<String>>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
view! { <Provider value=CheckboxGroupInjection(value) children/> }
|
view! {
|
||||||
|
<Provider value=CheckboxGroupInjection(value)>
|
||||||
|
<div class="thaw-checkbox-group" role="group">
|
||||||
|
{children()}
|
||||||
|
</div>
|
||||||
|
</Provider>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct CheckboxGroupInjection(pub Model<HashSet<String>>);
|
pub(crate) struct CheckboxGroupInjection(pub Model<HashSet<String>>);
|
||||||
|
|
||||||
pub(crate) fn use_checkbox_group() -> CheckboxGroupInjection {
|
impl CheckboxGroupInjection {
|
||||||
expect_context()
|
pub fn use_() -> Self {
|
||||||
|
expect_context()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::checkbox::{checkbox_group::use_checkbox_group, Checkbox};
|
use super::{checkbox_group::CheckboxGroupInjection, Checkbox};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use thaw_utils::OptionalProp;
|
use thaw_utils::OptionalProp;
|
||||||
|
|
||||||
|
@ -6,39 +6,39 @@ use thaw_utils::OptionalProp;
|
||||||
pub fn CheckboxItem(
|
pub fn CheckboxItem(
|
||||||
#[prop(optional, into)] label: Option<String>,
|
#[prop(optional, into)] label: Option<String>,
|
||||||
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
|
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
|
||||||
#[prop(into)] key: String,
|
#[prop(into)] value: String,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let checkbox_group_value = use_checkbox_group().0;
|
let group_value = CheckboxGroupInjection::use_().0;
|
||||||
let checked = RwSignal::new(false);
|
let checked = RwSignal::new(false);
|
||||||
let item_key = StoredValue::new(key);
|
let item_value = StoredValue::new(value);
|
||||||
|
|
||||||
let is_checked = Memo::new(move |_| {
|
let is_checked = Memo::new(move |_| {
|
||||||
checkbox_group_value.with(|value| item_key.with_value(|key| value.contains(key)))
|
group_value.with(|group_value| item_value.with_value(|value| group_value.contains(value)))
|
||||||
});
|
});
|
||||||
|
|
||||||
Effect::new(move |_| {
|
Effect::new(move |_| {
|
||||||
checked.track();
|
checked.track();
|
||||||
|
|
||||||
if is_checked.get_untracked() {
|
if is_checked.get_untracked() {
|
||||||
checkbox_group_value.update(move |value| {
|
group_value.update(move |group_value| {
|
||||||
item_key.with_value(|key| {
|
item_value.with_value(|value| {
|
||||||
value.remove(key);
|
group_value.remove(value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if checked.get_untracked() {
|
} else if checked.get_untracked() {
|
||||||
checkbox_group_value.update(move |value| {
|
group_value.update(move |group_value| {
|
||||||
value.insert(item_key.get_value());
|
group_value.insert(item_value.get_value());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(label) = label {
|
if let Some(label) = label {
|
||||||
view! {
|
view! {
|
||||||
<Checkbox class value=(is_checked, checked.write_only())>
|
<Checkbox class checked=(is_checked, checked.write_only())>
|
||||||
{label}
|
{label}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
view! { <Checkbox class value=(is_checked, checked.write_only())/> }
|
view! { <Checkbox class checked=(is_checked, checked.write_only())/> }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,38 +4,56 @@ mod checkbox_item;
|
||||||
pub use checkbox_group::CheckboxGroup;
|
pub use checkbox_group::CheckboxGroup;
|
||||||
pub use checkbox_item::CheckboxItem;
|
pub use checkbox_item::CheckboxItem;
|
||||||
|
|
||||||
use crate::icon::*;
|
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use thaw_components::*;
|
use thaw_components::*;
|
||||||
use thaw_utils::{class_list, mount_style, Model, OptionalProp};
|
use thaw_utils::{class_list, mount_style, Model, OptionalProp};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Checkbox(
|
pub fn Checkbox(
|
||||||
#[prop(optional, into)] value: Model<bool>,
|
#[prop(optional, into)] checked: Model<bool>,
|
||||||
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
|
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
|
||||||
#[prop(optional)] children: Option<Children>,
|
#[prop(optional)] children: Option<Children>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("checkbox", include_str!("./checkbox.css"));
|
mount_style("checkbox", include_str!("./checkbox.css"));
|
||||||
|
|
||||||
|
let id = uuid::Uuid::new_v4().to_string();
|
||||||
|
let input_ref = NodeRef::<html::Input>::new();
|
||||||
|
|
||||||
|
let on_change = move |_| {
|
||||||
|
let input = input_ref.get_untracked().unwrap();
|
||||||
|
checked.set(input.checked())
|
||||||
|
};
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div
|
<div
|
||||||
class=class_list![
|
class=class_list![
|
||||||
"thaw-checkbox", ("thaw-checkbox--checked", move || value.get()), class.map(| c |
|
"thaw-checkbox", ("thaw-checkbox--checked", move || checked.get()), class.map(| c |
|
||||||
move || c.get())
|
move || c.get())
|
||||||
]
|
]
|
||||||
|
|
||||||
on:click=move |_| value.set(!value.get_untracked())
|
|
||||||
>
|
>
|
||||||
<input class="thaw-checkbox__input" type="checkbox"/>
|
<input
|
||||||
|
class="thaw-checkbox__input"
|
||||||
|
type="checkbox"
|
||||||
|
id=id.clone()
|
||||||
|
checked=checked.get_untracked()
|
||||||
|
ref=input_ref
|
||||||
|
on:change=on_change
|
||||||
|
/>
|
||||||
<div class="thaw-checkbox__indicator">
|
<div class="thaw-checkbox__indicator">
|
||||||
<If cond=value.signal()>
|
{
|
||||||
<Then slot>
|
move || if checked.get() {
|
||||||
<Icon icon=icondata_ai::AiCheckOutlined style="color: white"/>
|
view! {
|
||||||
</Then>
|
<svg fill="currentColor" aria-hidden="true" width="12" height="12" viewBox="0 0 12 12" style="display: inline;line-height: 0">
|
||||||
</If>
|
<path d="M9.76 3.2c.3.29.32.76.04 1.06l-4.25 4.5a.75.75 0 0 1-1.08.02L2.22 6.53a.75.75 0 0 1 1.06-1.06l1.7 1.7L8.7 3.24a.75.75 0 0 1 1.06-.04Z" fill="currentColor"></path>
|
||||||
|
</svg>
|
||||||
|
}.into()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<OptionComp value=children let:children>
|
<OptionComp value=children let:children>
|
||||||
<label class="thaw-checkbox__label">{children()}</label>
|
<label class="thaw-checkbox__label" for=id>{children()}</label>
|
||||||
</OptionComp>
|
</OptionComp>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue