1use std::collections::HashMap;
4use std::ops::Deref;
5
6use once_cell::sync::Lazy;
7use yew::Properties;
8
9use crate::theme::breakpoint::Breakpoints;
10pub use color::Color;
11use regex::Regex;
12
13use crate::theme::palette::Palette;
14use crate::theme::typography::{TypographyLevel, TypographyScale};
15use crate::utils::to_property;
16
17pub mod color;
18
19pub mod baseline;
20pub mod breakpoint;
21pub mod gradient;
22pub mod palette;
23pub mod parsing;
24pub mod sx;
25pub mod theme_mode;
26pub mod typography;
27
28#[derive(Debug, Clone, PartialEq)]
29pub struct Theme {
30 pub prefix: String,
31 breakpoints: Breakpoints,
32 palettes: HashMap<String, Palette>,
33 typography: TypographyScale,
34}
35
36static DEFAULT_THEME: Lazy<Theme> = Lazy::new(|| {
37 parsing::from_str(include_str!("./theme/theme.json")).expect("could not read default theme")
38});
39
40impl Default for Theme {
41 fn default() -> Self {
42 DEFAULT_THEME.clone()
43 }
44}
45
46impl Theme {
47 pub fn new() -> Self {
48 Self::with_prefix("happy")
49 }
50
51 pub fn with_prefix(prefix: impl AsRef<str>) -> Self {
52 Self {
53 prefix: prefix.as_ref().to_string(),
54 breakpoints: Default::default(),
55 palettes: Default::default(),
56 typography: Default::default(),
57 }
58 }
59
60 pub fn get_palette(&self, name: &str) -> Option<&Palette> {
62 self.palettes.get(name)
63 }
64
65 pub fn palette_mut(&mut self, name: &str) -> Option<&mut Palette> {
67 self.palettes.get_mut(name)
68 }
69
70 pub fn insert_palette(&mut self, name: impl AsRef<str>, palette: Palette) {
72 let _ = self.palettes.insert(name.as_ref().to_string(), palette);
73 }
74
75 pub fn palette(&mut self, name: impl AsRef<str>) -> &mut Palette {
77 self.palettes.entry(name.as_ref().to_string()).or_default()
78 }
79
80 pub fn palette_var(&self, palette: &str, selector: &str) -> String {
81 to_property(format!("--{}-palette-{palette}-{selector}", self.prefix))
82 }
83
84 pub fn class_var(&self, class: &str, var_name: &str) -> String {
85 to_property(format!("--{}-{class}-{var_name}", self.prefix))
86 }
87
88 pub fn palettes(&self) -> impl Iterator<Item = (&str, &Palette)> {
90 self.palettes.iter().map(|(key, value)| (&**key, value))
91 }
92
93 pub fn breakpoints(&self) -> &Breakpoints {
95 &self.breakpoints
96 }
97
98 pub fn breakpoints_mut(&mut self) -> &mut Breakpoints {
100 &mut self.breakpoints
101 }
102
103 pub fn typography(&self) -> &TypographyScale {
105 &self.typography
106 }
107
108 pub fn typography_mut(&mut self) -> &mut TypographyScale {
110 &mut self.typography
111 }
112
113 pub fn system_class(&self) -> String {
114 format!(".{}-system", self.prefix)
115 }
116}
117
118pub static PALETTE_SELECTOR_REGEX: Lazy<Regex> = Lazy::new(|| {
119 Regex::new(r#"^(?<palette>[a-zA-Z_]\w*)\.(?<selector>\w+)$"#)
120 .expect("could not create palette selector")
121});