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