1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
use crate::prelude::*;
use gloo_net::http::Request;
use wasm_bindgen_futures::spawn_local;
use web_sys::RequestCache;
/// Properties for the Image component.
#[derive(Properties, Clone, PartialEq)]
pub struct ImageProps {
/// The source URL for the image.
pub src: &'static str,
/// The alternative text for the image.
pub alt: &'static str,
/// The width of the image.
pub width: &'static str,
/// The height of the image.
pub height: &'static str,
// Common props
#[prop_or_default]
/// The style attribute for the image.
pub style: &'static str,
#[prop_or_default]
/// The CSS class for the image.
pub class: &'static str,
#[prop_or_default]
/// The sizes attribute for the image.
pub sizes: &'static str,
#[prop_or_default]
/// The quality attribute for the image.
pub quality: &'static str,
#[prop_or_default]
/// Indicates if the image should have priority loading.
pub priority: bool,
#[prop_or_default]
/// The placeholder attribute for the image.
pub placeholder: &'static str,
#[prop_or_default]
/// Callback function for handling loading completion.
pub on_loading_complete: Callback<()>,
// Advanced Props
#[prop_or_default]
/// The object-fit attribute for the image.
pub object_fit: &'static str,
#[prop_or_default]
/// The object-position attribute for the image.
pub object_position: &'static str,
#[prop_or_default]
/// Callback function for handling errors during image loading.
pub on_error: Callback<String>,
#[prop_or_default]
/// The decoding attribute for the image.
pub decoding: &'static str,
#[prop_or_default]
/// The blur data URL for placeholder image.
pub blur_data_url: &'static str,
#[prop_or_default]
/// The lazy boundary for lazy loading.
pub lazy_boundary: &'static str,
#[prop_or_default]
/// Indicates if the image should be unoptimized.
pub unoptimized: bool,
// Other Props
#[prop_or_default]
/// Reference to the DOM node.
pub node_ref: NodeRef,
}
/// The Image component for displaying images with various options.
///
/// # Arguments
/// * `props` - The properties of the component.
///
/// # Returns
/// (Html): An HTML representation of the image component.
///
/// # Examples
/// ```
/// // Example of using the Image component
/// use next_rs::{Image, ImageProps};
/// use next_rs::prelude::*;
///
/// #[function_component(MyComponent)]
/// pub fn my_component() -> Html {
/// let image_props = ImageProps {
/// src: "images/logo.png",
/// alt: "Example Image",
/// width: "200",
/// height: "300",
/// style: "border: 1px solid #ddd;",
/// class: "image-class",
/// sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",
/// quality: "80",
/// priority: true,
/// placeholder: "blur",
/// on_loading_complete: Callback::from(|_| {
/// println!("Image loading is complete!");
/// }),
/// object_fit: "cover",
/// object_position: "center",
/// on_error: Callback::from(|err| {
/// println!("Error loading image: {:?}", err);
/// }),
/// decoding: "async",
/// blur_data_url: "data:image/png;base64,....",
/// lazy_boundary: "200px",
/// unoptimized: false,
/// node_ref: NodeRef::default(),
/// };
///
/// html! {
/// <Image ..image_props />
/// }
/// }
/// ```
#[function_component(Image)]
pub fn image(props: &ImageProps) -> Html {
let props = props.clone();
let fetch_data = {
Callback::from(move |_| {
let loader_url = props.src;
let loading_complete_callback = props.on_loading_complete.clone();
let on_error_callback = props.on_error.clone();
spawn_local(async move {
match Request::get(&loader_url)
.cache(RequestCache::Reload)
.send()
.await
{
Ok(response) => {
let json_result = response.json::<serde_json::Value>();
match json_result.await {
Ok(_data) => {
loading_complete_callback.emit(());
}
Err(_err) => {
let event = Event::new("error").unwrap();
on_error_callback.emit(event.to_string().into());
}
}
}
Err(_err) => {
let event = Event::new("error").unwrap();
on_error_callback.emit(event.to_string().into());
}
}
});
})
};
html! {
<img
src={props.src}
alt={props.alt}
width={props.width}
height={props.height}
style={props.style}
class={props.class}
loading={if props.priority { "eager" } else { "lazy" }}
sizes={props.sizes}
quality={props.quality}
placeholder={props.placeholder}
object-fit={props.object_fit}
object-position={props.object_position}
onerror={fetch_data.clone()}
decoding={props.decoding}
ref={props.node_ref}
/>
}
}