use leptos::{ev, html, prelude::*};
use orbital_base_components::{
ComponentRef, FieldInjection, Rule, TextareaRef, TextareaRuleTrigger,
};
use orbital_macros::component_doc;
use orbital_style::inject_style;
use super::styles::textarea_styles;
use super::types::{TextareaAppearance, TextareaBind, TextareaEvents};
#[component_doc(
category = "Inputs",
preview_slug = "textarea",
preview_label = "Textarea",
preview_icon = icondata::AiFormOutlined,
)]
#[component]
pub fn Textarea(
#[prop(optional, into)]
bind: TextareaBind,
#[prop(optional, into)]
appearance: TextareaAppearance,
#[prop(optional, into)]
events: TextareaEvents,
#[prop(optional, into)]
class: MaybeProp<String>,
#[prop(optional)]
comp_ref: ComponentRef<TextareaRef>,
) -> impl IntoView {
inject_style("orbital-textarea", textarea_styles());
let TextareaBind {
value,
id,
name,
rules,
} = bind;
let TextareaAppearance {
placeholder,
disabled,
resize,
size,
..
} = appearance;
let TextareaEvents {
on_focus,
on_blur,
allow_value,
} = events;
let (id, name) = FieldInjection::use_id_and_name(id, name);
let value = StoredValue::new(value);
let validate = Rule::validate(rules, value, name);
let on_input = {
let allow_value = allow_value.clone();
move |e| {
let input_value = event_target_value(&e);
if let Some(allow_value) = allow_value.as_ref() {
if !allow_value(input_value.clone()) {
value.with_value(|v| v.update(|_| {}));
return;
}
}
value.with_value(|v| v.set(input_value));
validate.run(Some(TextareaRuleTrigger::Input));
}
};
let on_change = move |_| {
validate.run(Some(TextareaRuleTrigger::Change));
};
let on_internal_focus = move |ev: ev::FocusEvent| {
if let Some(on_focus) = on_focus.as_ref() {
on_focus(ev);
}
validate.run(Some(TextareaRuleTrigger::Focus));
};
let on_internal_blur = move |ev: ev::FocusEvent| {
if let Some(on_blur) = on_blur.as_ref() {
on_blur(ev);
}
validate.run(Some(TextareaRuleTrigger::Blur));
};
let size_class = Memo::new(move |_| format!("orbital-textarea--{}", size.get().as_str()));
let resize_class =
Memo::new(move |_| format!("orbital-textarea--resize-{}", resize.get().as_str()));
let wrapper_class = Memo::new(move |_| {
let mut parts = vec![
"orbital-textarea".to_string(),
size_class.get(),
resize_class.get(),
];
if disabled.get() {
parts.push("orbital-textarea--disabled".to_string());
}
if let Some(extra) = class.get() {
if !extra.is_empty() {
parts.push(extra);
}
}
parts.join(" ")
});
let textarea_ref = NodeRef::<html::Textarea>::new();
comp_ref.load(TextareaRef::new(textarea_ref));
view! {
<span class=wrapper_class>
<textarea
class="orbital-textarea__textarea"
id=id
name=name
placeholder=move || placeholder.get()
disabled=move || disabled.get().then_some("")
prop:value=move || value.get_value().get()
on:input=on_input
on:change=on_change
on:focus=on_internal_focus
on:blur=on_internal_blur
node_ref=textarea_ref
/>
</span>
}
}