nova_forms/components/
choice.rs1use std::{fmt::Debug, marker::PhantomData, str::FromStr};
2
3use crate::{BaseGroupContext, GroupContext, QueryString};
4use leptos::*;
5
6mod context {
7 use super::*;
8
9 #[derive(Debug, Clone)]
10 pub struct ChoicesContext<T: Clone + Eq + 'static> {
11 selected: Signal<T>,
12 }
13
14 impl<T> ChoicesContext<T>
15 where
16 T: Clone + Eq + 'static
17 {
18 pub fn new<F>(f: F) -> Self
19 where
20 F: Fn() -> T + 'static,
21 {
22 Self {
23 selected: Signal::derive(f)
24 }
25 }
26
27 pub fn selected(&self, discriminant: T) -> Signal<bool> {
28 let selected = self.selected;
29 Signal::derive(move || selected.get() == discriminant)
30 }
31 }
32}
33
34pub(crate) use context::ChoicesContext;
35
36#[component]
38pub fn Choices<T>(
39 #[prop(into)] tag: QueryString,
41 #[prop(optional)] _phantom: PhantomData<T>,
42 children: Children,
44) -> impl IntoView
45where
46 T: Clone + Eq + Default + Debug + FromStr + 'static,
47 T::Err: Clone + Debug + 'static,
48{
49 let parent_group = expect_context::<GroupContext>();
50 let base_group = expect_context::<BaseGroupContext>();
51 let value: Signal<Result<T, <T as FromStr>::Err>> = Signal::derive(move || base_group
52 .get(parent_group.qs().join(tag))
53 .get()
54 .expect(&format!("tag {} not found", base_group.qs().join(tag)))
55 .as_input()
56 .expect("expected input, got group").value::<T>()
57 .get());
58
59 provide_context(ChoicesContext::new(move || value.get().unwrap_or_default()));
60
61 let children = children();
62
63 view! {
64 <div class="choices">
65 {children}
66 </div>
67 }
68}
69
70#[component]
71pub fn Choice<T>(
72 #[prop(into)] discriminant: T,
74 #[prop(optional)] children: Option<Children>,
75) -> impl IntoView
76where
77 T: Copy + Eq + 'static
78{
79 let context = expect_context::<ChoicesContext<T>>();
80
81 view! {
82 <div class=move || {
83 if context.selected(discriminant).get() { "choice selected" } else { "choice hidden" }
84 }>
85 {if let Some(children) = children { children().into_view() } else { View::default() }}
86 </div>
87 }
88}