dxc_components/image/
image.rs1use super::props::ImageProps;
2use crate::image_viewer::DxcImageViewer;
3use dioxus::prelude::*;
4use dxc_hooks::UseNamespace;
5use dxc_macros::classes;
6use dxc_types::{components::image::Loading, namespace::Block};
7
8#[component]
9pub fn DxcImage(props: ImageProps) -> Element {
10 let img_src = use_signal(|| props.src());
11 let alt = use_signal(|| props.alt());
12 let loading = use_signal(|| props.loading());
13 let lazy = use_signal(|| props.lazy());
14 let fit = use_signal(|| props.fit());
15 let initial_index = use_signal(|| props.initial_index());
16 let preview_src_list = use_signal(|| props.preview_src_list());
17 let crossorigin = use_signal(|| props.crossorigin());
18
19 let mut image_src = use_signal(|| String::new());
20
21 let mut has_load_error = use_signal(|| false);
22 let mut is_loading = use_signal(|| true);
23 let mut show_viewer = use_signal(|| false);
24 let support_loading = use_signal(|| false);
25 let preview = use_signal(|| preview_src_list.len() > 0);
26
27 let image_index = use_memo(move || {
28 let mut preview_index = initial_index();
29
30 if let Some(next) = preview_src_list().len().checked_sub(1) {
31 if initial_index() > next {
32 preview_index = 0;
33 }
34 }
35
36 preview_index
37 });
38
39 let is_manual = use_signal(|| {
40 if loading() == Loading::Lazy {
41 return false;
42 }
43
44 return !support_loading() && loading() == Loading::Lazy || lazy();
45 });
46
47 let mut laod_image = move || {
48 is_loading.set(true);
49 has_load_error.set(false);
50 image_src.set(img_src());
51 };
52
53 let handle_lazy_load = move || {
54 laod_image();
55 };
56
57 let ns = UseNamespace::new(Block::Image, None);
64
65 let image_classes = classes! {
66 ns.e_(String::from("inner")),
67 if preview() { &ns.e_(String::from("preview")) },
68 if is_loading() { &ns.e_(String::from("loading")) },
69 };
70
71 let image_style = format!("object-fit: {};", fit());
72
73 rsx! {
74 div {
75 class: ns.b(),
76
77 if has_load_error() {
80 div {
81 "name": "image_error",
82 div {
83 class: ns.e_(String::from("error")),
84 "FAILED"
85 }
86 {props.error}
87 }
88 } else {
89 div {
90 if !img_src().is_empty(){
93 img {
94 src: img_src(),
95 alt: alt(),
96 class: image_classes,
97 style: image_style,
98 loading: loading(),
99 crossorigin: crossorigin(),
100 onclick: move |_| {
101 if !preview() {
102 return;
103 }
104
105 show_viewer.set(true);
106 },
107 onload: move |_| {
108 is_loading.set(false);
109 has_load_error.set(false);
110 },
111 onerror: move |_| {
112 is_loading.set(false);
113 has_load_error.set(true);
114 },
115 }
116 }
117
118 if is_loading() {
119 div {
120 class: ns.e_(String::from("wrapper")),
121 div {
122 class: ns.e_(String::from("placeholder")),
123 {props.placeholder}
124 }
125 }
126 }
127 }
128 }
129
130 if preview() {
131 if show_viewer() {
132 DxcImageViewer{
133 z_index: props.z_index,
134 initial_index: image_index(),
135 infinite: props.infinite,
136 zoom_rate: props.zoom_rate,
137 min_scale: props.min_scale,
138 max_scale: props.max_scale,
139 show_progress: props.show_progress,
140 url_list: preview_src_list(),
141 crossorigin: crossorigin(),
142 onclose: move |_| {
146 show_viewer.set(false);
147 },
148 }
152 }
153 }
154 }
155 }
156}