use iced::widget::{Svg, svg};
use iced::{Color, Length, Theme};
pub use lucide_static_svg::Icon;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Glyph {
name: &'static str,
svg: &'static str,
}
impl Glyph {
pub const fn new(icon: Icon) -> Self {
Self {
name: icon.name(),
svg: icon.svg_str(),
}
}
pub const fn name(self) -> &'static str {
self.name
}
pub const fn svg(self) -> &'static str {
self.svg
}
}
#[macro_export]
macro_rules! lucide {
($name:ident) => {{
const GLYPH: $crate::icon::Glyph = $crate::icon::Glyph::new($crate::icon::Icon::$name);
GLYPH
}};
}
pub const DISABLED_OPACITY: f32 = 0.5;
pub const fn opacity(enabled: bool) -> f32 {
if enabled { 1.0 } else { DISABLED_OPACITY }
}
pub fn icon<'a>(glyph: Glyph, size: f32) -> Svg<'a, Theme> {
themed(glyph, size, 1.0, |theme| {
theme.extended_palette().background.base.text
})
}
pub fn tinted<'a>(glyph: Glyph, size: f32, color: Option<Color>) -> Svg<'a, Theme> {
match color {
Some(color) => themed(glyph, size, color.a, move |_| color),
None => icon(glyph, size),
}
}
pub fn themed<'a>(
glyph: Glyph,
size: f32,
opacity: f32,
color: impl Fn(&Theme) -> Color + 'a,
) -> Svg<'a, Theme> {
svg(svg::Handle::from_memory(glyph.svg().as_bytes()))
.width(Length::Fixed(size))
.height(Length::Fixed(size))
.opacity(opacity.clamp(0.0, 1.0))
.style(move |theme: &Theme, _status| svg::Style {
color: Some(opaque(color(theme))),
})
}
pub const fn opaque(color: Color) -> Color {
Color { a: 1.0, ..color }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn disabled_icons_are_drawn_at_half_opacity() {
assert_eq!(opacity(true), 1.0);
assert_eq!(opacity(false), DISABLED_OPACITY);
}
#[test]
fn opaque_keeps_the_channels_and_drops_the_alpha() {
let colour = opaque(Color::from_rgba(0.1, 0.2, 0.3, 0.4));
assert_eq!(colour, Color::from_rgb(0.1, 0.2, 0.3));
}
#[test]
fn macro_resolves_name_and_markup() {
let glyph = crate::lucide!(ChevronRight);
assert_eq!(glyph.name(), "chevron-right");
assert!(glyph.svg().starts_with("<svg"));
}
#[test]
fn lucide_svgs_use_current_colour_so_tinting_works() {
assert!(crate::lucide!(Save).svg().contains("currentColor"));
}
}