flams_router_vscode/
components.rs

1#![allow(clippy::must_use_candidate)]
2
3use ftml_dom::utils::css::inject_css;
4pub use leptos::prelude::*;
5
6#[component]
7pub fn VSCodeButton(children: Children) -> AnyView {
8    inject_css("flams-vscode-button", include_str!("button.css"));
9    //let children = children.into_inner();
10    view!(<button class="flams-vscode-button">{children()}</button>).into_any()
11}
12
13struct RadioGroup {
14    name: String,
15    selected: RwSignal<Option<String>>,
16}
17
18#[component]
19pub fn VSCodeRadioGroup(
20    #[prop(into)] name: String,
21    selected: RwSignal<Option<String>>,
22    children: Children,
23) -> AnyView {
24    inject_css("flams-vscode-radio", include_str!("radio.css"));
25    //let children = children.into_inner();
26    provide_context(RadioGroup { name, selected });
27    children()
28}
29
30#[component]
31pub fn VSCodeRadio(
32    #[prop(into)] id: String,
33    children: Children,
34    #[prop(optional, into)] disabled: Option<Signal<bool>>,
35) -> AnyView {
36    //let children = children.into_inner();
37    let Some((name, selected)) = with_context(|g: &RadioGroup| (g.name.clone(), g.selected)) else {
38        panic!("VSCodeRadio outside of VSCodeRadioGroup");
39    };
40    let idc = id.clone();
41    let checked = Memo::new(move |_| {
42        if selected.with(|s| s.as_ref().is_some_and(|s| *s == idc)) {
43            "icon checked"
44        } else {
45            "icon"
46        }
47    });
48    let top_class = Memo::new(move |_| {
49        if disabled.is_some_and(|b| b.get()) {
50            "flams-vscode-radio disabled"
51        } else {
52            "flams-vscode-radio"
53        }
54    });
55    let idc = id.clone();
56    let on_click = move |_| {
57        if !disabled.is_some_and(|b| b.get()) {
58            selected.set(Some(idc.clone()));
59        }
60    };
61    view! {
62        <div class=top_class on:click=on_click><div class="wrapper">
63            <input type="radio" id=id.clone() name=name checked=checked disabled=disabled/>
64            <div class=checked></div>
65            <label for=id><div>
66                {children()}
67            </div></label>
68        </div></div>
69    }.into_any()
70}
71
72#[component]
73pub fn VSCodeCheckbox(
74    checked: RwSignal<bool>,
75    children: Children,
76    #[prop(optional, into)] disabled: Option<Signal<bool>>,
77) -> AnyView {
78    inject_css("flams-vscode-checkbox", include_str!("checkbox.css"));
79    //let children = children.into_inner();
80
81    let top_class = Memo::new(move |_| {
82        if disabled.is_some_and(|b| b.get()) {
83            "flams-vscode-checkbox disabled"
84        } else {
85            "flams-vscode-checkbox"
86        }
87    });
88    let on_click = move |_| {
89        if !disabled.is_some_and(|b| b.get()) {
90            checked.update(|v| *v = !*v);
91        }
92    };
93    view! {
94        <div class=top_class on:click=on_click><div class="wrapper">
95            <input type="checkbox" checked=checked disabled=disabled/>
96            <div class="icon">
97                {move || if checked.get() {Some(view!{
98                    <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="check-icon">
99                        <path fill-rule="evenodd" clip-rule="evenodd" d="M14.431 3.323l-8.47 10-.79-.036-3.35-4.77.818-.574 2.978 4.24 8.051-9.506.764.646z"></path>
100                    </svg>
101                })} else {None}}
102            </div>
103            <label><div>
104                {children()}
105            </div></label>
106        </div></div>
107    }.into_any()
108}
109
110#[component]
111pub fn VSCodeTextbox(
112    value: RwSignal<String>,
113    #[prop(optional)] placeholder: Option<&'static str>,
114    #[prop(optional, into)] disabled: Option<Signal<bool>>,
115) -> impl IntoView {
116    inject_css("flams-vscode-textbox", include_str!("textbox.css"));
117    view! {
118        <input type="text" placeholder=placeholder bind:value=value class="flams-vscode-textbox" disabled=disabled></input>
119    }.into_any()
120}