impulse_thaw/combobox/
combobox_option.rs1use super::listbox::ListboxInjection;
2use crate::ComboboxInjection;
3use leptos::prelude::*;
4use thaw_components::{Fallback, If, OptionComp, Then};
5use thaw_utils::class_list;
6
7#[component]
8pub fn ComboboxOption(
9 #[prop(optional, into)] class: MaybeProp<String>,
10 #[prop(optional, into)]
13 disabled: Signal<bool>,
14 #[prop(optional, into)]
16 value: Option<String>,
17 #[prop(into)]
20 text: String,
21 #[prop(optional)] children: Option<Children>,
22) -> impl IntoView {
23 let combobox = ComboboxInjection::expect_context();
24 let listbox = ListboxInjection::expect_context();
25 let value = StoredValue::new(value.unwrap_or_else(|| text.clone()));
26 let text = StoredValue::new(text);
27 let is_selected = Memo::new(move |_| value.with_value(|value| combobox.is_selected(&value)));
28 let id = uuid::Uuid::new_v4().to_string();
29
30 let on_click = move |_| {
31 if disabled.get_untracked() {
32 return;
33 }
34 text.with_value(|text| {
35 value.with_value(|value| {
36 combobox.select_option(value, text);
37 });
38 });
39 };
40
41 {
42 combobox.insert_option(id.clone(), (value.get_value(), text.get_value(), disabled));
43 let id = id.clone();
44 listbox.trigger();
45 on_cleanup(move || {
46 combobox.remove_option(&id);
47 listbox.trigger();
48 });
49 }
50
51 view! {
52 <div
53 role="option"
54 aria-disabled=move || if disabled.get() { "true" } else { "" }
55 aria-selected=move || is_selected.get().to_string()
56 id=id
57 class=class_list![
58 "thaw-combobox-option",
59 ("thaw-combobox-option--selected", move || is_selected.get()),
60 ("thaw-combobox-option--disabled", move || disabled.get()),
61 class
62 ]
63 on:click=on_click
64 >
65 {if combobox.multiselect {
66 view! {
67 <span aria-hidden="true" class="thaw-combobox-option__check-icon--multiselect">
68 <If cond=is_selected>
69 <Then slot>
70 <svg
71 fill="currentColor"
72 aria-hidden="true"
73 width="12"
74 height="12"
75 viewBox="0 0 12 12"
76 >
77 <path
78 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"
79 fill="currentColor"
80 ></path>
81 </svg>
82 </Then>
83 </If>
84 </span>
85 }
86 .into_any()
87 } else {
88 view! {
89 <span aria-hidden="true" class="thaw-combobox-option__check-icon">
90 <svg
91 fill="currentColor"
92 aria-hidden="true"
93 width="1em"
94 height="1em"
95 viewBox="0 0 20 20"
96 >
97 <path
98 d="M7.03 13.9 3.56 10a.75.75 0 0 0-1.12 1l4 4.5c.29.32.79.34 1.09.03l10.5-10.5a.75.75 0 0 0-1.06-1.06l-9.94 9.94Z"
99 fill="currentColor"
100 ></path>
101 </svg>
102 </span>
103 }
104 .into_any()
105 }}
106 <OptionComp value=children let:children>
107 <Fallback slot>{text.get_value()}</Fallback>
108 {children()}
109 </OptionComp>
110 </div>
111 }
112}