mod rule;
mod types;
pub use rule::*;
pub use types::*;
use crate::{FieldInjection, Rule};
use leptos::{ev, html, prelude::*};
use thaw_utils::{class_list, mount_style, BoxOneCallback, ComponentRef, Model};
#[component]
pub fn Textarea(
#[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional, into)] id: MaybeProp<String>,
#[prop(optional, into)]
name: MaybeProp<String>,
#[prop(optional, into)]
rules: Vec<TextareaRule>,
#[prop(optional, into)]
value: Model<String>,
#[prop(optional, into)]
allow_value: Option<BoxOneCallback<String, bool>>,
#[prop(optional, into)]
placeholder: MaybeProp<String>,
#[prop(optional, into)]
on_focus: Option<BoxOneCallback<ev::FocusEvent>>,
#[prop(optional, into)]
on_blur: Option<BoxOneCallback<ev::FocusEvent>>,
#[prop(optional, into)]
disabled: Signal<bool>,
#[prop(optional, into)]
resize: Signal<TextareaResize>,
#[prop(optional, into)]
size: Signal<TextareaSize>,
#[prop(optional)] comp_ref: ComponentRef<TextareaRef>,
) -> impl IntoView {
mount_style("textarea", include_str!("./textarea.css"));
let (id, name) = FieldInjection::use_id_and_name(id, name);
let validate = Rule::validate(rules, value, name);
let value_trigger = ArcTrigger::new();
let on_input = {
let value_trigger = value_trigger.clone();
move |ev| {
let input_value = event_target_value(&ev);
if let Some(allow_value) = allow_value.as_ref() {
if !allow_value(input_value.clone()) {
value_trigger.notify();
return;
}
}
value.set(input_value);
validate.run(Some(TextareaRuleTrigger::Input));
}
};
let on_change = move |_| {
validate.run(Some(TextareaRuleTrigger::Change));
};
let on_internal_focus = move |ev| {
if let Some(on_focus) = on_focus.as_ref() {
on_focus(ev);
}
validate.run(Some(TextareaRuleTrigger::Focus));
};
let on_internal_blur = move |ev| {
if let Some(on_blur) = on_blur.as_ref() {
on_blur(ev);
}
validate.run(Some(TextareaRuleTrigger::Blur));
};
let textarea_ref = NodeRef::<html::Textarea>::new();
comp_ref.load(TextareaRef { textarea_ref });
view! {
<span class=class_list![
"thaw-textarea",
("thaw-textarea--disabled", move || disabled.get()),
move || format!("thaw-textarea--resize-{}", resize.get().as_str()),
move || format!("thaw-textarea--{}", size.get().as_str()),
class
]>
<textarea
prop:value=move || {
value_trigger.track();
value.get()
}
on:input=on_input
on:change=on_change
on:focus=on_internal_focus
on:blur=on_internal_blur
class="thaw-textarea__textarea"
id=id
name=name
disabled=move || disabled.get()
placeholder=move || placeholder.get()
node_ref=textarea_ref
></textarea>
</span>
}
}