yew_bs/components/
image.rs

1use yew::prelude::*;
2#[derive(Properties, PartialEq)]
3pub struct ImageProps {
4    pub src: AttrValue,
5    #[prop_or_default]
6    pub alt: Option<AttrValue>,
7    #[prop_or_default]
8    pub width: Option<AttrValue>,
9    #[prop_or_default]
10    pub height: Option<AttrValue>,
11    #[prop_or_default]
12    pub fluid: bool,
13    #[prop_or_default]
14    pub thumbnail: bool,
15    #[prop_or_default]
16    pub rounded: Option<ImageRounded>,
17    #[prop_or_default]
18    pub float_start: bool,
19    #[prop_or_default]
20    pub float_end: bool,
21    #[prop_or_default]
22    pub float_sm_start: bool,
23    #[prop_or_default]
24    pub float_sm_end: bool,
25    #[prop_or_default]
26    pub float_md_start: bool,
27    #[prop_or_default]
28    pub float_md_end: bool,
29    #[prop_or_default]
30    pub float_lg_start: bool,
31    #[prop_or_default]
32    pub float_lg_end: bool,
33    #[prop_or_default]
34    pub float_xl_start: bool,
35    #[prop_or_default]
36    pub float_xl_end: bool,
37    #[prop_or_default]
38    pub float_xxl_start: bool,
39    #[prop_or_default]
40    pub float_xxl_end: bool,
41    #[prop_or_default]
42    pub class: Option<AttrValue>,
43    #[prop_or_default]
44    pub node_ref: NodeRef,
45    #[prop_or_default]
46    pub loading: Option<ImageLoading>,
47    #[prop_or_default]
48    pub decoding: Option<ImageDecoding>,
49    #[prop_or_default]
50    pub title: Option<AttrValue>,
51    #[prop_or_default]
52    pub onclick: Option<Callback<MouseEvent>>,
53}
54#[derive(Clone, Copy, PartialEq, Debug)]
55pub enum ImageRounded {
56    Circle,
57    Rounded,
58    RoundedTop,
59    RoundedBottom,
60    RoundedStart,
61    RoundedEnd,
62    None,
63}
64impl ImageRounded {
65    pub fn as_str(&self) -> &'static str {
66        match self {
67            ImageRounded::Circle => "rounded-circle",
68            ImageRounded::Rounded => "rounded",
69            ImageRounded::RoundedTop => "rounded-top",
70            ImageRounded::RoundedBottom => "rounded-bottom",
71            ImageRounded::RoundedStart => "rounded-start",
72            ImageRounded::RoundedEnd => "rounded-end",
73            ImageRounded::None => "",
74        }
75    }
76}
77/// Image loading behavior
78#[derive(Clone, Copy, PartialEq, Debug)]
79pub enum ImageLoading {
80    /// Load image immediately
81    Eager,
82    /// Defer loading until image is near viewport
83    Lazy,
84}
85impl ImageLoading {
86    pub fn as_str(&self) -> &'static str {
87        match self {
88            ImageLoading::Eager => "eager",
89            ImageLoading::Lazy => "lazy",
90        }
91    }
92}
93#[derive(Clone, Copy, PartialEq, Debug)]
94pub enum ImageDecoding {
95    Auto,
96    Sync,
97    Async,
98}
99impl ImageDecoding {
100    pub fn as_str(&self) -> &'static str {
101        match self {
102            ImageDecoding::Auto => "auto",
103            ImageDecoding::Sync => "sync",
104            ImageDecoding::Async => "async",
105        }
106    }
107}
108/// Bootstrap Image component
109#[function_component(Image)]
110pub fn image(props: &ImageProps) -> Html {
111    let mut classes = Classes::new();
112    if props.fluid {
113        classes.push("img-fluid");
114    }
115    if props.thumbnail {
116        classes.push("img-thumbnail");
117    }
118    if let Some(rounded) = &props.rounded {
119        let rounded_class = rounded.as_str();
120        if !rounded_class.is_empty() {
121            classes.push(rounded_class);
122        }
123    }
124    if props.float_start {
125        classes.push("float-start");
126    }
127    if props.float_end {
128        classes.push("float-end");
129    }
130    if props.float_sm_start {
131        classes.push("float-sm-start");
132    }
133    if props.float_sm_end {
134        classes.push("float-sm-end");
135    }
136    if props.float_md_start {
137        classes.push("float-md-start");
138    }
139    if props.float_md_end {
140        classes.push("float-md-end");
141    }
142    if props.float_lg_start {
143        classes.push("float-lg-start");
144    }
145    if props.float_lg_end {
146        classes.push("float-lg-end");
147    }
148    if props.float_xl_start {
149        classes.push("float-xl-start");
150    }
151    if props.float_xl_end {
152        classes.push("float-xl-end");
153    }
154    if props.float_xxl_start {
155        classes.push("float-xxl-start");
156    }
157    if props.float_xxl_end {
158        classes.push("float-xxl-end");
159    }
160    if let Some(class) = &props.class {
161        classes.push(class.to_string());
162    }
163    html! {
164        < img src = { props.src.clone() } alt = { props.alt.clone() } width = { props
165        .width.clone() } height = { props.height.clone() } class = { classes } ref = {
166        props.node_ref.clone() } loading = { props.loading.as_ref().map(| l | l.as_str())
167        } decoding = { props.decoding.as_ref().map(| d | d.as_str()) } title = { props
168        .title.clone() } onclick = { props.onclick.clone() } />
169    }
170}
171/// Props for the Figure component
172#[derive(Properties, PartialEq)]
173pub struct FigureProps {
174    /// Figure children (Image and Figcaption)
175    #[prop_or_default]
176    pub children: Children,
177    /// Additional CSS classes
178    #[prop_or_default]
179    pub class: Option<AttrValue>,
180    /// Additional HTML attributes
181    #[prop_or_default]
182    pub node_ref: NodeRef,
183}
184/// Bootstrap Figure component
185#[function_component(Figure)]
186pub fn figure(props: &FigureProps) -> Html {
187    let mut classes = Classes::new();
188    classes.push("figure");
189    if let Some(class) = &props.class {
190        classes.push(class.to_string());
191    }
192    html! {
193        < figure class = { classes } ref = { props.node_ref.clone() } > { for props
194        .children.iter() } </ figure >
195    }
196}
197/// Props for the Figcaption component
198#[derive(Properties, PartialEq)]
199pub struct FigcaptionProps {
200    /// Figcaption children
201    #[prop_or_default]
202    pub children: Children,
203    /// Additional CSS classes
204    #[prop_or_default]
205    pub class: Option<AttrValue>,
206    /// Additional HTML attributes
207    #[prop_or_default]
208    pub node_ref: NodeRef,
209}
210/// Bootstrap Figcaption component
211#[function_component(Figcaption)]
212pub fn figcaption(props: &FigcaptionProps) -> Html {
213    let mut classes = Classes::new();
214    classes.push("figure-caption");
215    if let Some(class) = &props.class {
216        classes.push(class.to_string());
217    }
218    html! {
219        < figcaption class = { classes } ref = { props.node_ref.clone() } > { for props
220        .children.iter() } </ figcaption >
221    }
222}