@@ -0,0 +1,101 @@
+use std::collections::HashMap;
+
+use gpui2::Rgba;
+
+use crate::scale::{ColorScaleName, ColorScaleSet, ColorScales};
+
+struct DefaultColorScaleSet {
+ scale: ColorScaleName,
+ light: [&'static str; 12],
+ light_alpha: [&'static str; 12],
+ dark: [&'static str; 12],
+ dark_alpha: [&'static str; 12],
+}
+
+impl From<DefaultColorScaleSet> for ColorScaleSet {
+ fn from(default: DefaultColorScaleSet) -> Self {
+ Self::new(
+ default.scale,
+ default
+ .light
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ default
+ .light_alpha
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ default
+ .dark
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ default
+ .dark_alpha
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ )
+ }
+}
+
+pub fn default_color_scales() -> ColorScales {
+ use ColorScaleName::*;
+
+ HashMap::from_iter([(Red, red().into())])
+}
+
+fn red() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Red,
+ light: [
+ "#fffcfc00",
+ "#fff7f700",
+ "#feebec00",
+ "#ffdbdc00",
+ "#ffcdce00",
+ "#fdbdbe00",
+ "#f4a9aa00",
+ "#eb8e9000",
+ "#e5484d00",
+ "#dc3e4200",
+ "#ce2c3100",
+ "#64172300",
+ ],
+ light_alpha: [
+ "#ff000003",
+ "#ff000008",
+ "#f3000d14",
+ "#ff000824",
+ "#ff000632",
+ "#f8000442",
+ "#df000356",
+ "#d2000571",
+ "#db0007b7",
+ "#d10005c1",
+ "#c40006d3",
+ "#55000de8",
+ ],
+ dark: [
+ "#19111100",
+ "#20131400",
+ "#3b121900",
+ "#500f1c00",
+ "#61162300",
+ "#72232d00",
+ "#8c333a00",
+ "#b5454800",
+ "#e5484d00",
+ "#ec5d5e00",
+ "#ff959200",
+ "#ffd1d900",
+ ],
+ dark_alpha: [
+ "#f4121209",
+ "#f22f3e11",
+ "#ff173f2d",
+ "#fe0a3b44",
+ "#ff204756",
+ "#ff3e5668",
+ "#ff536184",
+ "#ff5d61b0",
+ "#fe4e54e4",
+ "#ff6465eb",
+ "#ff959200",
+ "#ffd1d900",
+ ],
+ }
+}
@@ -0,0 +1,166 @@
+use std::collections::HashMap;
+
+use gpui2::{AppContext, Hsla};
+
+use crate::{theme, Appearance};
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum ColorScaleName {
+ Gray,
+ Mauve,
+ Slate,
+ Sage,
+ Olive,
+ Sand,
+ Gold,
+ Bronze,
+ Brown,
+ Yellow,
+ Amber,
+ Orange,
+ Tomato,
+ Red,
+ Ruby,
+ Crimson,
+ Pink,
+ Plum,
+ Purple,
+ Violet,
+ Iris,
+ Indigo,
+ Blue,
+ Cyan,
+ Teal,
+ Jade,
+ Green,
+ Grass,
+ Lime,
+ Mint,
+ Sky,
+ Black,
+ White,
+}
+
+impl std::fmt::Display for ColorScaleName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ Self::Gray => "Gray",
+ Self::Mauve => "Mauve",
+ Self::Slate => "Slate",
+ Self::Sage => "Sage",
+ Self::Olive => "Olive",
+ Self::Sand => "Sand",
+ Self::Gold => "Gold",
+ Self::Bronze => "Bronze",
+ Self::Brown => "Brown",
+ Self::Yellow => "Yellow",
+ Self::Amber => "Amber",
+ Self::Orange => "Orange",
+ Self::Tomato => "Tomato",
+ Self::Red => "Red",
+ Self::Ruby => "Ruby",
+ Self::Crimson => "Crimson",
+ Self::Pink => "Pink",
+ Self::Plum => "Plum",
+ Self::Purple => "Purple",
+ Self::Violet => "Violet",
+ Self::Iris => "Iris",
+ Self::Indigo => "Indigo",
+ Self::Blue => "Blue",
+ Self::Cyan => "Cyan",
+ Self::Teal => "Teal",
+ Self::Jade => "Jade",
+ Self::Green => "Green",
+ Self::Grass => "Grass",
+ Self::Lime => "Lime",
+ Self::Mint => "Mint",
+ Self::Sky => "Sky",
+ Self::Black => "Black",
+ Self::White => "White",
+ }
+ )
+ }
+}
+
+pub type ColorScale = [Hsla; 12];
+
+pub type ColorScales = HashMap<ColorScaleName, ColorScaleSet>;
+
+pub struct ColorScaleSet {
+ name: ColorScaleName,
+ light: ColorScale,
+ dark: ColorScale,
+ light_alpha: ColorScale,
+ dark_alpha: ColorScale,
+}
+
+impl ColorScaleSet {
+ pub fn new(
+ name: ColorScaleName,
+ light: ColorScale,
+ light_alpha: ColorScale,
+ dark: ColorScale,
+ dark_alpha: ColorScale,
+ ) -> Self {
+ Self {
+ name,
+ light,
+ light_alpha,
+ dark,
+ dark_alpha,
+ }
+ }
+
+ pub fn name(&self) -> String {
+ self.name.to_string()
+ }
+
+ pub fn light(&self, step: usize) -> Hsla {
+ self.light[step - 1]
+ }
+
+ pub fn light_alpha(&self, step: usize) -> Hsla {
+ self.light_alpha[step - 1]
+ }
+
+ pub fn dark(&self, step: usize) -> Hsla {
+ self.dark[step - 1]
+ }
+
+ pub fn dark_alpha(&self, step: usize) -> Hsla {
+ self.dark[step - 1]
+ }
+
+ fn current_appearance(cx: &AppContext) -> Appearance {
+ let theme = theme(cx);
+ if theme.metadata.is_light {
+ Appearance::Light
+ } else {
+ Appearance::Dark
+ }
+ }
+
+ /// Returns the one-based step in the scale.
+ ///
+ /// We usually reference steps as 1-12 instead of 0-11, so we
+ /// automatically subtract 1 from the index.
+ pub fn step(self, cx: &AppContext, index: usize) -> Hsla {
+ let appearance = Self::current_appearance(cx);
+
+ match appearance {
+ Appearance::Light => self.light(index),
+ Appearance::Dark => self.dark(index),
+ }
+ }
+
+ pub fn step_alpha(self, cx: &AppContext, index: usize) -> Hsla {
+ let appearance = Self::current_appearance(cx);
+ match appearance {
+ Appearance::Light => self.light_alpha(index),
+ Appearance::Dark => self.dark_alpha(index),
+ }
+ }
+}