100 lines
3.1 KiB
Rust
100 lines
3.1 KiB
Rust
use leptos::html;
|
|
use leptos::prelude::*;
|
|
use strum::AsRefStr;
|
|
use tw_merge::tw_merge;
|
|
|
|
#[derive(Default, Clone, Copy, PartialEq, Eq, AsRefStr)]
|
|
#[strum(serialize_all = "lowercase")]
|
|
#[allow(dead_code)]
|
|
pub enum InputType {
|
|
#[default]
|
|
Text,
|
|
Email,
|
|
Password,
|
|
Number,
|
|
Tel,
|
|
Url,
|
|
Search,
|
|
Date,
|
|
Time,
|
|
#[strum(serialize = "datetime-local")]
|
|
DatetimeLocal,
|
|
Month,
|
|
Week,
|
|
Color,
|
|
File,
|
|
Hidden,
|
|
}
|
|
|
|
#[component]
|
|
pub fn Input(
|
|
#[prop(into, optional)] class: String,
|
|
#[prop(default = InputType::default())] r#type: InputType,
|
|
#[prop(into, optional)] placeholder: Option<String>,
|
|
#[prop(into, optional)] name: Option<String>,
|
|
#[prop(into, optional)] id: Option<String>,
|
|
#[prop(into, optional)] title: Option<String>,
|
|
#[prop(optional)] disabled: bool,
|
|
#[prop(optional)] readonly: bool,
|
|
#[prop(optional)] required: bool,
|
|
#[prop(optional)] autofocus: bool,
|
|
#[prop(into, optional)] min: Option<String>,
|
|
#[prop(into, optional)] max: Option<String>,
|
|
#[prop(into, optional)] step: Option<String>,
|
|
#[prop(into, optional)] bind_value: Option<RwSignal<String>>,
|
|
#[prop(optional)] node_ref: NodeRef<html::Input>,
|
|
) -> impl IntoView {
|
|
let merged_class = tw_merge!(
|
|
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
"focus-visible:border-ring focus-visible:ring-ring/50",
|
|
"focus-visible:ring-2",
|
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
"read-only:bg-muted",
|
|
class
|
|
);
|
|
|
|
let type_str = r#type.as_ref();
|
|
|
|
match bind_value {
|
|
Some(signal) => view! {
|
|
<input
|
|
data-name="Input"
|
|
type=type_str
|
|
class=merged_class
|
|
placeholder=placeholder
|
|
name=name
|
|
id=id
|
|
title=title
|
|
disabled=disabled
|
|
readonly=readonly
|
|
required=required
|
|
autofocus=autofocus
|
|
min=min
|
|
max=max
|
|
step=step
|
|
bind:value=signal
|
|
node_ref=node_ref
|
|
/>
|
|
}.into_any(),
|
|
None => view! {
|
|
<input
|
|
data-name="Input"
|
|
type=type_str
|
|
class=merged_class
|
|
placeholder=placeholder
|
|
name=name
|
|
id=id
|
|
title=title
|
|
disabled=disabled
|
|
readonly=readonly
|
|
required=required
|
|
autofocus=autofocus
|
|
min=min
|
|
max=max
|
|
step=step
|
|
node_ref=node_ref
|
|
/>
|
|
}.into_any(),
|
|
}
|
|
}
|