use crate::prelude::ValidationResult;
use crate::theme::prelude::*;
use dominator::{html, Dom, DomBuilder};
use dwind::prelude::*;
use futures_signals::signal::Signal;
use futures_signals::signal::SignalExt;
use futures_signals::signal::not;
use web_sys::HtmlElement;
pub fn field_surface_mixin(
label: impl Signal<Item = String> + 'static,
raise_label: impl Signal<Item = bool> + 'static,
validation_signal: impl Signal<Item = ValidationResult> + 'static,
input_id: String,
) -> impl FnOnce(DomBuilder<HtmlElement>) -> DomBuilder<HtmlElement> {
move |b| {
let raise_label = raise_label.broadcast();
let label = label.broadcast();
let validation_signal = validation_signal.broadcast();
let is_valid = validation_signal
.signal_ref(|validation| validation.is_valid())
.broadcast();
let b = dwclass!(b, "dwui-field-surface relative w-full rounded-md overflow-hidden");
let b = dwclass!(b, "dwui-bg-void-900 is(.light *):dwui-bg-void-200");
let b = dwclass!(b, "border-b-2 transition-colors");
let b = dwclass_signal!(
b,
"dwui-border-void-500 is(.light *):dwui-border-void-400",
is_valid.signal()
);
let b = dwclass_signal!(
b,
"dwui-border-error-500 is(.light *):dwui-border-error-600",
not(is_valid.signal())
);
b.child(html!("label", {
.attr("for", &input_id)
.dwclass!("absolute pointer-events-none select-none p-l-3 text-base")
.dwclass_signal!("dwui-text-on-primary-400 is(.light *):dwui-text-on-primary-600", is_valid.signal())
.dwclass_signal!("dwui-text-error-500 is(.light *):dwui-text-error-600", not(is_valid.signal()))
.style("left", "0")
.style("line-height", "1")
.style("top", "var(--dwui-field-label-top, 50%)")
.style("transform-origin", "left top")
.style("transition", "transform 150ms ease, color 150ms ease")
.style_signal("transform", raise_label.signal().map(|raised| {
if raised {
"translateY(-100%) scale(0.75)"
} else {
"translateY(-50%)"
}
}))
.text_signal(label.signal_cloned())
}))
}
}
pub fn field_error_row(
validation_signal: impl Signal<Item = ValidationResult> + 'static,
input_id: &str,
) -> Dom {
let message = validation_signal
.map(|validation| match validation {
ValidationResult::Valid => "".to_string(),
ValidationResult::Invalid { message } => message,
})
.broadcast();
html!("div", {
.attr("id", &format!("{}-error", input_id))
.attr_signal("role", message.signal_ref(|m| {
if m.is_empty() {
None
} else {
Some("alert")
}
}))
.dwclass!("min-h-5 text-sm p-l-3 pointer-events-none")
.dwclass!("dwui-text-error-500 is(.light *):dwui-text-error-700")
.text_signal(message.signal_cloned())
})
}