thaw/src/input/mod.rs

118 lines
3.7 KiB
Rust
Raw Normal View History

2023-04-06 17:27:54 +08:00
mod theme;
2023-10-07 21:41:03 +08:00
2023-05-30 23:00:30 +08:00
use crate::{
theme::{use_theme, Theme},
2023-10-11 21:25:11 +08:00
utils::{maybe_rw_signal::MaybeRwSignal, mount_style::mount_style},
2023-05-30 23:00:30 +08:00
};
2023-04-03 17:31:50 +08:00
use leptos::*;
2023-05-30 23:00:30 +08:00
pub use theme::InputTheme;
2023-04-03 17:31:50 +08:00
2023-06-19 21:53:39 +08:00
#[derive(Default, Clone)]
2023-10-08 14:01:24 +08:00
pub enum InputVariant {
2023-06-19 21:53:39 +08:00
#[default]
2023-10-16 21:15:43 +08:00
Text,
Password,
2023-06-19 21:53:39 +08:00
}
2023-10-08 14:01:24 +08:00
impl InputVariant {
2023-06-19 21:53:39 +08:00
pub fn as_str(&self) -> &'static str {
match self {
2023-10-16 21:15:43 +08:00
InputVariant::Text => "text",
InputVariant::Password => "password",
2023-06-19 21:53:39 +08:00
}
}
}
#[slot]
pub struct InputSuffix {
children: Children,
}
2023-04-03 17:31:50 +08:00
#[component]
pub fn Input(
2023-10-11 21:25:11 +08:00
#[prop(optional, into)] value: MaybeRwSignal<String>,
2023-10-15 12:23:26 +08:00
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
2023-10-08 14:01:24 +08:00
#[prop(optional, into)] variant: MaybeSignal<InputVariant>,
2023-10-15 12:23:26 +08:00
#[prop(optional, into)] placeholder: MaybeSignal<String>,
#[prop(optional, into)] on_focus: Option<Callback<ev::FocusEvent>>,
#[prop(optional, into)] on_blur: Option<Callback<ev::FocusEvent>>,
#[prop(optional)] input_suffix: Option<InputSuffix>,
2023-04-03 17:31:50 +08:00
) -> impl IntoView {
2023-08-29 09:11:22 +08:00
let theme = use_theme(Theme::light);
2023-10-07 21:41:03 +08:00
mount_style("input", include_str!("./input.css"));
2023-05-30 23:00:30 +08:00
2023-10-18 16:12:13 +08:00
let value_trigger = create_trigger();
2023-10-15 12:23:26 +08:00
let on_input = move |ev| {
let input_value = event_target_value(&ev);
if let Some(allow_value) = allow_value.as_ref() {
if !allow_value.call(input_value.clone()) {
2023-10-18 16:12:13 +08:00
value_trigger.notify();
2023-10-15 12:23:26 +08:00
return;
}
}
value.set(input_value);
};
2023-11-03 13:58:29 +08:00
let is_focus = create_rw_signal(false);
2023-10-15 12:23:26 +08:00
let on_internal_focus = move |ev| {
2023-11-03 13:58:29 +08:00
is_focus.set(true);
2023-10-15 12:23:26 +08:00
if let Some(on_focus) = on_focus.as_ref() {
on_focus.call(ev);
}
};
let on_internal_blur = move |ev| {
2023-11-03 13:58:29 +08:00
is_focus.set(false);
2023-10-15 12:23:26 +08:00
if let Some(on_blur) = on_blur.as_ref() {
on_blur.call(ev);
}
};
2023-05-30 23:00:30 +08:00
2023-08-29 09:11:22 +08:00
let css_vars = create_memo(move |_| {
2023-04-06 17:27:54 +08:00
let mut css_vars = String::new();
2023-10-26 23:24:16 +08:00
theme.with(|theme| {
let border_color_hover = theme.common.color_primary.clone();
2023-11-05 16:03:58 +08:00
css_vars.push_str(&format!("--thaw-border-color-hover: {border_color_hover};"));
css_vars.push_str(&format!("--thaw-box-shadow-color: {border_color_hover}33;"));
2023-10-26 23:24:16 +08:00
let border_radius = theme.common.border_radius.clone();
2023-11-05 16:03:58 +08:00
css_vars.push_str(&format!("--thaw-border-radius: {border_radius};"));
2023-10-26 23:24:16 +08:00
css_vars.push_str(&format!(
2023-11-05 16:03:58 +08:00
"--thaw-background-color: {};",
2023-10-26 23:24:16 +08:00
theme.input.background_color
));
2023-11-05 16:03:58 +08:00
css_vars.push_str(&format!("--thaw-font-color: {};", theme.input.font_color));
2023-10-26 23:24:16 +08:00
css_vars.push_str(&format!(
2023-11-05 16:03:58 +08:00
"--thaw-border-color: {};",
2023-10-26 23:24:16 +08:00
theme.input.border_color
));
css_vars.push_str(&format!(
2023-11-05 16:03:58 +08:00
"--thaw-placeholder-color: {};",
2023-10-26 23:24:16 +08:00
theme.input.placeholder_color
));
});
2023-04-06 17:27:54 +08:00
css_vars
});
2023-04-03 17:31:50 +08:00
view! {
2023-11-05 16:03:58 +08:00
<div class="thaw-input" class=("thaw-input--focus", move || is_focus.get()) style=move || css_vars.get()>
2023-10-08 09:28:13 +08:00
<input
2023-10-08 14:01:24 +08:00
type=move || variant.get().as_str()
2023-10-18 16:12:13 +08:00
prop:value=move || {
value_trigger.track();
value.get()
}
2023-11-02 22:01:48 +08:00
2023-10-15 12:23:26 +08:00
on:input=on_input
on:focus=on_internal_focus
on:blur=on_internal_blur
2023-11-05 16:03:58 +08:00
class="thaw-input__input-el"
2023-10-15 12:23:26 +08:00
placeholder=move || placeholder.get()
2023-10-08 09:28:13 +08:00
/>
2023-11-02 22:01:48 +08:00
{if let Some(suffix) = input_suffix {
2023-11-05 16:03:58 +08:00
view! { <div class="thaw-input__suffix">{(suffix.children)()}</div> }.into()
2023-11-02 22:01:48 +08:00
} else {
None
}}
2023-04-03 17:31:50 +08:00
</div>
}
}