impulse_thaw/select/
select.rs1use super::{SelectRule, SelectSize};
2
3use crate::{icon::ChevronDownRegularIcon, FieldInjection, Rule, SelectRuleTrigger};
4use leptos::{html, prelude::*};
5use thaw_utils::{class_list, mount_style, Model};
6
7#[component]
8pub fn Select(
9 #[prop(optional, into)] class: MaybeProp<String>,
10 #[prop(optional, into)] id: MaybeProp<String>,
11 #[prop(optional, into)] rules: Vec<SelectRule>,
12 #[prop(optional, into)]
15 name: MaybeProp<String>,
16 #[prop(optional, into)] value: Model<String>,
17 #[prop(optional, into)] default_value: Option<String>,
18 #[prop(optional, into)]
20 disabled: Signal<bool>,
21 #[prop(optional, into)]
23 size: Signal<SelectSize>,
24 children: Children,
25) -> impl IntoView {
26 mount_style("select", include_str!("./select.css"));
27 let (id, name) = FieldInjection::use_id_and_name(id, name);
28 let validate = Rule::validate(rules, value, name);
29 let select_ref = NodeRef::<html::Select>::new();
30 Effect::new(move |prev: Option<bool>| {
31 let Some(el) = select_ref.get() else {
32 return false;
33 };
34
35 let el_value = el.value();
36 if !prev.unwrap_or_default() {
37 if let Some(default_value) = default_value.as_ref() {
38 el.set_value(default_value);
39 value.set(default_value.clone());
40 } else {
41 value.set(el_value);
42 }
43 value.with(|_| {});
44 return true;
45 }
46 value.with(|value| {
47 if value != &el_value {
48 el.set_value(value);
49 }
50 });
51 true
52 });
53
54 let on_change = move |_| {
55 let Some(el) = select_ref.get() else {
56 return;
57 };
58 value.set(el.value());
59 validate.run(Some(SelectRuleTrigger::Change));
60 };
61
62 view! {
63 <span class=class_list![
64 "thaw-select",
65 ("thaw-select--disabled", move || disabled.get()),
66 move || format!("thaw-select--{}", size.get().as_str()),
67 class
68 ]>
69 <select
70 class="thaw-select__select"
71 id=id
72 name=name
73 node_ref=select_ref
74 disabled=disabled
75 on:change=on_change
76 >
77 {children()}
78 </select>
79 <span class="thaw-select__icon">
80 <ChevronDownRegularIcon />
81 </span>
82 </span>
83 }
84}