use std::borrow::Cow;
use iced_plus_tokens::{presets, Color as TokenColor, Shade, ThemeTokens};
#[derive(Debug, Clone)]
pub struct AppTheme<'a> {
tokens: Cow<'a, ThemeTokens>,
name: &'static str,
}
impl AppTheme<'static> {
#[must_use]
pub fn light() -> Self {
Self {
tokens: Cow::Owned(presets::light_tokens()),
name: "light",
}
}
#[must_use]
pub fn dark() -> Self {
Self {
tokens: Cow::Owned(presets::dark_tokens()),
name: "dark",
}
}
}
impl<'a> AppTheme<'a> {
#[must_use]
pub fn custom(tokens: ThemeTokens, name: &'static str) -> Self {
Self {
tokens: Cow::Owned(tokens),
name,
}
}
#[must_use]
pub fn from_ref(tokens: &'a ThemeTokens, name: &'static str) -> Self {
Self {
tokens: Cow::Borrowed(tokens),
name,
}
}
#[must_use]
pub const fn name(&self) -> &'static str {
self.name
}
#[must_use]
pub fn tokens(&self) -> &ThemeTokens {
&self.tokens
}
#[must_use]
pub fn spacing(&self) -> &iced_plus_tokens::SpacingScale {
&self.tokens.spacing
}
#[must_use]
pub fn colors(&self) -> &iced_plus_tokens::ColorPalette {
&self.tokens.colors
}
#[must_use]
pub fn typography(&self) -> &iced_plus_tokens::TypographyScale {
&self.tokens.typography
}
#[must_use]
pub fn radius(&self) -> &iced_plus_tokens::RadiusScale {
&self.tokens.radius
}
#[must_use]
pub fn elevation(&self) -> &iced_plus_tokens::ElevationScale {
&self.tokens.elevation
}
#[must_use]
pub fn motion(&self) -> &iced_plus_tokens::MotionScale {
&self.tokens.motion
}
#[must_use]
pub fn primary(&self, shade: Shade) -> iced::Color {
token_to_iced(self.tokens.colors.primary.get(shade))
}
#[must_use]
pub fn secondary(&self, shade: Shade) -> iced::Color {
token_to_iced(self.tokens.colors.secondary.get(shade))
}
#[must_use]
pub fn neutral(&self, shade: Shade) -> iced::Color {
token_to_iced(self.tokens.colors.neutral.get(shade))
}
#[must_use]
pub fn success(&self, shade: Shade) -> iced::Color {
token_to_iced(self.tokens.colors.semantic.success.get(shade))
}
#[must_use]
pub fn warning(&self, shade: Shade) -> iced::Color {
token_to_iced(self.tokens.colors.semantic.warning.get(shade))
}
#[must_use]
pub fn destructive(&self, shade: Shade) -> iced::Color {
token_to_iced(self.tokens.colors.semantic.destructive.get(shade))
}
#[must_use]
pub fn info(&self, shade: Shade) -> iced::Color {
token_to_iced(self.tokens.colors.semantic.info.get(shade))
}
#[must_use]
pub fn background(&self) -> iced::Color {
if self.name == "dark" {
self.neutral(Shade::S900)
} else {
self.neutral(Shade::S50)
}
}
#[must_use]
pub fn surface(&self) -> iced::Color {
if self.name == "dark" {
self.neutral(Shade::S800)
} else {
iced::Color::WHITE
}
}
#[must_use]
pub fn text(&self) -> iced::Color {
if self.name == "dark" {
self.neutral(Shade::S100)
} else {
self.neutral(Shade::S900)
}
}
#[must_use]
pub fn text_muted(&self) -> iced::Color {
if self.name == "dark" {
self.neutral(Shade::S400)
} else {
self.neutral(Shade::S500)
}
}
#[must_use]
pub fn border(&self) -> iced::Color {
if self.name == "dark" {
self.neutral(Shade::S700)
} else {
self.neutral(Shade::S200)
}
}
}
impl Default for AppTheme<'static> {
fn default() -> Self {
Self::light()
}
}
#[must_use]
pub fn token_to_iced(color: TokenColor) -> iced::Color {
iced::Color::from_rgba(color.r, color.g, color.b, color.a)
}