yew_google_material/icons/
mod.rs1use stylist::Style;
54use yew::prelude::*;
55use crate::GIconStyle;
56use web_sys::Element;
57
58#[derive(Debug, Properties, PartialEq, Clone)]
59pub struct GIconProps {
60 pub icon: AttrValue,
61 pub icon_style: GIconStyle,
62 #[prop_or_else(|| false )]
63 pub fill: bool,
64 #[prop_or_else(|| AttrValue::from("300"))]
65 pub wght: AttrValue,
66 #[prop_or_else(|| AttrValue::from("100"))]
67 pub grade: AttrValue,
68 #[prop_or_else(|| AttrValue::from("24"))]
69 pub opsz: AttrValue,
70 #[prop_or_else(|| AttrValue::from(r#"inherit"#))]
71 pub color: AttrValue,
72 #[prop_or_else(|| AttrValue::from(r#"24px"#))]
73 pub size: AttrValue,
74 #[prop_or_else(|| AttrValue::from("unset"))]
75 pub transition: AttrValue,
76 #[prop_or_default]
77 pub leading_icon: bool,
78 #[prop_or_default]
79 pub trailing_icon: bool,
80}
81
82#[function_component(GIcon)]
83pub fn icon(props: &GIconProps) -> Html {
84 let universal_slyle = match props.icon_style {
85 GIconStyle::Outlined => "material-symbols-outlined",
86 GIconStyle::Rounded => "material-symbols-rounded",
87 GIconStyle::Sharp => "material-symbols-sharp",
88 };
89 let fill = if props.fill { 1_u8 } else { 0_u8 };
90 let wght = {
91 match props.wght.parse::<u16>() {
92 Ok(x) => {if x >= 100 && x <= 700 {x} else {panic!("Wrong Google Material Icon wght setting")}},
93 Err(_) => panic!("Wrong Google Material Icon wght setting"),
94 }
95 };
96 let grade = {
97 match props.grade.parse::<i16>() {
98 Ok(x) => {if x >= -50 && x <= 200 {x} else {panic!("Wrong Google Material Icon grade setting")}},
99 Err(_) => panic!("Wrong Google Material Icon grade setting"),
100 }
101 };
102 let opsz = {
103 match props.opsz.parse::<u8>() {
104 Ok(x) => {if x >= 20 && x <= 48 {x} else {panic!("Wrong Google Material Icon opsz setting")}},
105 Err(_) => panic!("Wrong Google Material Icon opsz setting"),
106 }
107 };
108
109 let color = props.color.clone();
110 let transition = props.transition.clone();
111 let size = props.size.clone();
112 let leading_icon = props.leading_icon.clone();
113 let trailing_icon = props.trailing_icon.clone();
114
115 let style_str = format!(
116 r#"
117 .{universal_slyle} {{
118 display: block;
119 transition: {transition};
120 color: {color};
121 font-size: {size};
122 font-variation-settings:
123 'FILL' {fill},
124 'wght' {wght},
125 'GRAD' {grade},
126 'opsz' {opsz}
127 }}
128 "#
129 );
130
131 let node_ref = NodeRef::default();
132 let node_ref_clone = node_ref.clone();
133
134 let style = Style::new(style_str).expect("Failed to create style");
135
136 use_effect(move || {
137 if leading_icon || trailing_icon {
138 let gicon = node_ref_clone.cast::<Element>().unwrap();
139 if leading_icon {
140 gicon.set_class_name("g_has_leading_icon");
141 }
142 if trailing_icon {
143 gicon.set_class_name("g_has_trailing_icon");
144 }
145 };
146 ()
147 });
148
149 html! {
150 <gicon ref={node_ref} style="line-height: 0">
151 <div class={style} style="line-height: 0">
152 <span class={universal_slyle}>{props.icon.clone()}</span>
153 </div>
154 </gicon>
155 }
156}