use super::*;
#[component]
pub fn euv_image(node: VirtualNode<EuvImageProps>) -> VirtualNode {
let EuvImageProps {
src,
alt,
placeholder,
width,
height,
}: EuvImageProps = node.try_get_props().unwrap_or_default();
let status: Signal<EuvImageStatus> =
HookContext::use_hook(|| Signal::create(EuvImageStatus::Loading));
let current: EuvImageStatus = status.get();
let size_style: String = image_size_style(width, height);
let size_ref: &str = size_style.as_str();
html! {
div {
class: c_euv_image()
class: match current {
EuvImageStatus::Loaded => c_euv_image(),
EuvImageStatus::Failed => c_euv_image_failed(),
EuvImageStatus::Loading => c_euv_image_placeholder(),
}
style: size_ref
if current != EuvImageStatus::Loaded && !placeholder.is_empty() {
span {
placeholder
}
}
img {
src: src
alt: alt
loading: "lazy"
onload: on_image_loaded(status)
onerror: on_image_failed(status)
}
}
}
}
fn image_size_style(width: Option<u32>, height: Option<u32>) -> String {
match (width, height) {
(Some(width), Some(height)) => format!("width: {width}px; height: {height}px;"),
(Some(width), None) => format!("width: {width}px;"),
(None, Some(height)) => format!("height: {height}px;"),
(None, None) => String::new(),
}
}
fn on_image_loaded(status: Signal<EuvImageStatus>) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_event: Event| {
status.set(EuvImageStatus::Loaded);
}))
}
fn on_image_failed(status: Signal<EuvImageStatus>) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_event: Event| {
status.set(EuvImageStatus::Failed);
}))
}