use leptos::prelude::*;
use crate::meta::DisabledState;
#[derive(Clone, Copy, PartialEq, Default, Debug)]
pub enum FieldValidationState {
#[default]
Idle,
Valid,
Invalid,
Warning,
}
impl FieldValidationState {
pub fn as_str(&self) -> &'static str {
match self {
Self::Idle => "idle",
Self::Valid => "valid",
Self::Invalid => "invalid",
Self::Warning => "warning",
}
}
pub fn aria_invalid(&self) -> Option<&'static str> {
match self { Self::Invalid => Some("true"), _ => None }
}
}
#[component]
pub fn FieldPrimitive(
children: Children,
#[prop(default = FieldValidationState::Idle)] validation: FieldValidationState,
#[prop(default = DisabledState::Enabled)] disabled: DisabledState,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
let uid_fi = crate::infra::uid::generate("fi");
view! {
<div
data-rs-field=""
data-rs-uid=uid_fi
data-rs-interaction="init"
data-rs-validation=validation.as_str()
data-rs-disabled=if disabled.disabled() { Some("disabled") } else { None }
aria-invalid=validation.aria_invalid()
aria-disabled=disabled.aria_disabled()
class=class
>
{children()}
</div>
}
}
#[component]
pub fn FieldLabelPrimitive(
children: Children,
#[prop(into, default = String::new())] html_for: String,
#[prop(default = false)] required: bool,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<label
data-rs-field-label=""
for={if html_for.is_empty() { None } else { Some(html_for) }}
data-rs-required={if required { Some("") } else { None }}
aria-required={if required { Some("true") } else { None }}
class=class
>
{children()}
</label>
}
}
#[component]
pub fn FieldDescriptionPrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<div data-rs-field-description="" class=class>
{children()}
</div>
}
}
#[component]
pub fn FieldErrorPrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<div
data-rs-field-error=""
role="alert"
aria-live="assertive"
class=class
>
{children()}
</div>
}
}
#[component]
pub fn FieldGroupPrimitive(
children: Children,
#[prop(into, optional)] aria_label: Option<String>,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<div
data-rs-field-group=""
role="group"
aria-label=aria_label
class=class
>
{children()}
</div>
}
}
#[component]
pub fn FieldSetPrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<fieldset data-rs-fieldset="" class=class>
{children()}
</fieldset>
}
}
#[component]
pub fn FieldLegendPrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! {
<legend data-rs-field-legend="" class=class>
{children()}
</legend>
}
}
#[component]
pub fn FieldContentPrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! { <div data-rs-field-content="" class=class>{children()}</div> }
}
#[component]
pub fn FieldTitlePrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! { <div data-rs-field-title="" class=class>{children()}</div> }
}
#[component]
pub fn FieldSeparatorWrapperPrimitive(
children: Children,
#[prop(into, default = String::new())] class: String,
) -> impl IntoView {
view! { <div data-rs-field-separator-wrapper="" class=class>{children()}</div> }
}
#[component]
pub fn FieldSeparatorContentPrimitive(
children: Children,
) -> impl IntoView {
view! { <span data-rs-field-separator-content="">{children()}</span> }
}
#[component]
pub fn FieldErrorItemPrimitive(
children: Children,
) -> impl IntoView {
view! { <span data-rs-field-error-item="">{children()}</span> }
}