From 4690b8d95ddfbda659329171b10efcfa05a202e1 Mon Sep 17 00:00:00 2001 From: luoxiaozero <48741584+luoxiaozero@users.noreply.github.com> Date: Sun, 25 Feb 2024 17:13:13 +0800 Subject: [PATCH] feat: Adds RadioGroup component (#117) * feat: Adds RadioGroup component * fix: RadioItem select --- demo_markdown/docs/radio/mod.md | 37 ++++++++++++++++++++++++++- thaw/src/radio/mod.rs | 12 +++++++-- thaw/src/radio/radio_group.rs | 17 +++++++++++++ thaw/src/radio/radio_item.rs | 44 +++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 thaw/src/radio/radio_group.rs create mode 100644 thaw/src/radio/radio_item.rs diff --git a/demo_markdown/docs/radio/mod.md b/demo_markdown/docs/radio/mod.md index 6eb9c3b..87d5b84 100644 --- a/demo_markdown/docs/radio/mod.md +++ b/demo_markdown/docs/radio/mod.md @@ -8,10 +8,45 @@ view! { } ``` +### Group + +```rust demo +let value = create_rw_signal(None); + +view! { + + + "Apple" + + + "Orange" + + +
+ "value: " {move || format!("{:?}", value.get())} +
+} +``` + ### Radio Props | Name | Type | Default | Description | | -------- | ----------------------------------- | -------------------- | ---------------------------------------- | | class | `OptionalProp>` | `Default::default()` | Addtional classes for the radio element. | | value | `Model` | `false` | Checked value. | -| children | `Children` | | Radio's content. | +| children | `Option` | `None` | Radio's content. | + +### RadioGroup Props + +| Name | Type | Default | Description | +| -------- | ----------------------- | -------------------- | ---------------------------------- | +| value | `Model>` | `Default::default()` | Sets the value of the radio group. | +| children | `Children` | | RadioGroup's content. | + +### RadioItem Props + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| class | `OptionalProp>` | `Default::default()` | Addtional classes for the radio element. | +| key | `String` | | The key of the radio to be used in a radio group. | +| children | `Option` | `None` | Radio's content. | diff --git a/thaw/src/radio/mod.rs b/thaw/src/radio/mod.rs index 124205e..8ee46fc 100644 --- a/thaw/src/radio/mod.rs +++ b/thaw/src/radio/mod.rs @@ -1,3 +1,9 @@ +mod radio_group; +mod radio_item; + +pub use radio_group::RadioGroup; +pub use radio_item::RadioItem; + use crate::{ theme::use_theme, utils::{class_list::class_list, mount_style, Model, OptionalProp}, @@ -9,7 +15,7 @@ use leptos::*; pub fn Radio( #[prop(optional, into)] value: Model, #[prop(optional, into)] class: OptionalProp>, - children: Children, + #[prop(optional)] children: Option, ) -> impl IntoView { let theme = use_theme(Theme::light); mount_style("radio", include_str!("./radio.css")); @@ -36,7 +42,9 @@ pub fn Radio( >
-
{children()}
+
+ {children.map(|children| children())} +
} } diff --git a/thaw/src/radio/radio_group.rs b/thaw/src/radio/radio_group.rs new file mode 100644 index 0000000..0efd55b --- /dev/null +++ b/thaw/src/radio/radio_group.rs @@ -0,0 +1,17 @@ +use crate::utils::Model; +use leptos::*; + +#[component] +pub fn RadioGroup( + #[prop(optional, into)] value: Model>, + children: Children, +) -> impl IntoView { + view! { } +} + +#[derive(Clone)] +pub(crate) struct RadioGroupInjection(pub Model>); + +pub(crate) fn use_radio_group() -> RadioGroupInjection { + expect_context() +} diff --git a/thaw/src/radio/radio_item.rs b/thaw/src/radio/radio_item.rs new file mode 100644 index 0000000..0a393e8 --- /dev/null +++ b/thaw/src/radio/radio_item.rs @@ -0,0 +1,44 @@ +use crate::{ + radio::{radio_group::use_radio_group, Radio}, + utils::OptionalProp, +}; +use leptos::*; + +#[component] +pub fn RadioItem( + #[prop(optional, into)] class: OptionalProp>, + #[prop(into)] key: String, + #[prop(optional)] children: Option, +) -> impl IntoView { + let radio_group_value = use_radio_group().0; + let checked = RwSignal::new(false); + let item_key = store_value(key); + + let is_checked = Memo::new(move |_| { + radio_group_value.with(|value| item_key.with_value(|key| value.as_ref() == Some(key))) + }); + + Effect::new(move |prev| { + let checked = checked.get(); + if prev.is_some() { + if !is_checked.get_untracked() { + radio_group_value.set(Some(item_key.get_value())) + } + } + + checked + }); + + if let Some(children) = children { + view! { + + {children()} + + } + } else { + view! { + + + } + } +}