use std::borrow::Cow;
use serde::{Deserialize, Serialize};
use teksilo_tokens::{ColorTokens, LayoutTokens, MotionTokens, ShapeTokens, TypographyTokens};
use crate::styles::component_style_slots::ComponentStyleSlots;
use crate::styles::theme_appearance::ThemeAppearance;
use crate::styles::theme_extension::ThemeExtensions;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ThemeId(Cow<'static, str>);
impl ThemeId {
pub fn new(id: impl Into<Cow<'static, str>>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Default for ThemeId {
fn default() -> Self {
Self(Cow::Borrowed("custom"))
}
}
impl std::fmt::Display for ThemeId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Theme {
#[serde(default)]
pub id: ThemeId,
pub appearance: ThemeAppearance,
pub colors: ColorTokens,
pub layout: LayoutTokens,
pub typography: TypographyTokens,
pub shape: ShapeTokens,
pub motion: MotionTokens,
#[serde(skip, default)]
pub style_slots: ComponentStyleSlots,
#[serde(skip, default)]
pub extensions: ThemeExtensions,
}
impl Theme {
pub fn new(
appearance: ThemeAppearance,
colors: ColorTokens,
layout: LayoutTokens,
typography: TypographyTokens,
shape: ShapeTokens,
motion: MotionTokens,
) -> Self {
Self {
id: ThemeId::default(),
appearance,
colors,
layout,
typography,
shape,
motion,
style_slots: ComponentStyleSlots::default(),
extensions: ThemeExtensions::new(),
}
}
pub fn with_id(mut self, id: impl Into<Cow<'static, str>>) -> Self {
self.id = ThemeId::new(id);
self
}
pub fn is_dark(&self) -> bool {
self.appearance.is_dark()
}
pub fn for_inactive_window(&self) -> Theme {
Theme {
colors: self.colors.for_inactive_window(),
..self.clone()
}
}
pub fn for_high_contrast(&self) -> Theme {
Theme {
colors: self.colors.for_high_contrast(),
..self.clone()
}
}
pub fn extension<T: std::any::Any + Send + Sync>(&self) -> Option<&T> {
self.extensions.get::<T>()
}
pub fn with_extension<T: std::any::Any + Send + Sync>(mut self, value: T) -> Self {
self.extensions.insert(value);
self
}
}