1use crate::{unit::*, Color, Style, StyleUpdater};
2use derive_rich::Rich;
3use std::fmt;
4
5#[derive(Clone, Debug, PartialEq, From, Display)]
41pub enum BoxShadow {
42 One(ShadowValue),
43 #[display(
44 fmt = "{}",
45 "_0.iter().map(|s| s.to_string()).collect::<Vec<_>>().join(\", \")"
46 )]
47 Multiple(Vec<ShadowValue>),
48 #[display(fmt = "initial")]
49 Initial,
50 #[display(fmt = "inherit")]
51 Inherit,
52 #[display(fmt = "none")]
53 None,
54 #[display(fmt = "unset")]
55 Unset,
56}
57
58impl Default for BoxShadow {
59 fn default() -> Self {
60 BoxShadow::Multiple(vec![])
61 }
62}
63
64impl StyleUpdater for BoxShadow {
65 fn update_style(self, style: Style) -> Style {
66 style.insert("box-shadow", self)
67 }
68}
69
70impl BoxShadow {
71 fn shadow(mut self, conf: impl FnOnce(ShadowValue) -> ShadowValue) -> Self {
72 self = match self {
73 Self::One(shadow) => Self::One(conf(shadow)),
74 Self::Multiple(shadows) => {
75 Self::One(conf(shadows.into_iter().next().unwrap_or_default()))
76 }
77 _ => Self::One(conf(ShadowValue::default())),
78 };
79 self
80 }
81
82 pub fn new() -> Self {
83 BoxShadow::Multiple(vec![])
84 }
85
86 pub fn x(self, val: impl Into<Length>) -> Self {
87 self.shadow(|sh| sh.x(val))
88 }
89
90 pub fn y(self, val: impl Into<Length>) -> Self {
91 self.shadow(|sh| sh.y(val))
92 }
93
94 pub fn blur(self, val: impl Into<Length>) -> Self {
95 self.shadow(|sh| sh.blur(val))
96 }
97
98 pub fn try_blur(self, val: Option<impl Into<Length>>) -> Self {
99 self.shadow(|sh| sh.try_blur(val))
100 }
101
102 pub fn spread(self, val: impl Into<Length>) -> Self {
103 self.shadow(|sh| sh.spread(val))
104 }
105
106 pub fn try_spread(self, val: Option<impl Into<Length>>) -> Self {
107 self.shadow(|sh| sh.try_spread(val))
108 }
109
110 pub fn color(self, val: impl Into<Color>) -> Self {
111 self.shadow(|sh| sh.color(val))
112 }
113
114 pub fn try_color(self, val: Option<impl Into<Color>>) -> Self {
115 self.shadow(|sh| sh.try_color(val))
116 }
117
118 pub fn inset(self) -> Self {
119 self.shadow(|sh| sh.inset())
120 }
121
122 pub fn outset(self) -> Self {
123 self.shadow(|sh| sh.outset())
124 }
125
126 pub fn push(mut self, get_val: impl FnOnce(ShadowValue) -> ShadowValue) -> Self {
127 let val = get_val(ShadowValue::default());
128 self = match self {
129 Self::Multiple(mut vec) => {
130 vec.push(val);
131 Self::Multiple(vec)
132 }
133 _ => Self::Multiple(vec![val]),
134 };
135 self
136 }
137}
138
139#[derive(Rich, Clone, Debug, PartialEq)]
140pub struct ShadowValue {
141 #[rich(write)]
142 x: Length,
143 #[rich(write)]
144 y: Length,
145 #[rich(write, write(option))]
146 blur: Option<Length>,
147 #[rich(write, write(option))]
148 spread: Option<Length>,
149 #[rich(write, write(option))]
150 color: Option<Color>,
151 #[rich(value_fns = { inset = true, outset = false })]
152 inset: bool,
153}
154
155impl fmt::Display for ShadowValue {
156 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157 if self.inset {
158 write!(f, "inset ")?;
159 }
160
161 write!(f, "{} {}", self.x, self.y)?;
162
163 match (self.blur.as_ref(), self.spread.as_ref()) {
164 (Some(blur), Some(spread)) => write!(f, " {} {}", blur, spread)?,
165 (Some(blur), None) => write!(f, " {}", blur)?,
166 (None, Some(spread)) => write!(f, " {} {}", px(0), spread)?,
168 (None, None) => {}
169 };
170
171 if let Some(color) = self.color {
172 write!(f, " {}", color)?;
173 }
174
175 Ok(())
176 }
177}
178
179impl Default for ShadowValue {
180 fn default() -> Self {
181 Self {
182 x: px(0),
183 y: px(0),
184 blur: None,
185 spread: None,
186 color: None,
187 inset: false,
188 }
189 }
190}