1mod picker;
8
9use std::rc::Rc;
10
11use gpui::{App, Global, Hsla, SharedString};
12use theme::{Appearance, Theme};
13
14pub use picker::{ColorPicker, ColorPickerEvent, parse_hex, to_hex};
15
16#[derive(Clone, Debug, PartialEq)]
18pub struct Swatch {
19 pub name: SharedString,
21 pub light: Hsla,
22 pub dark: Hsla,
23}
24
25impl Swatch {
26 pub fn new(
27 name: impl Into<SharedString>,
28 light: impl Into<Hsla>,
29 dark: impl Into<Hsla>,
30 ) -> Self {
31 Self {
32 name: name.into(),
33 light: light.into(),
34 dark: dark.into(),
35 }
36 }
37
38 pub fn fixed(name: impl Into<SharedString>, color: impl Into<Hsla>) -> Self {
40 let color = color.into();
41 Self::new(name, color, color)
42 }
43
44 pub fn resolve(&self, theme: &Theme) -> Hsla {
46 match theme.appearance {
47 Appearance::Light => self.light,
48 Appearance::Dark => self.dark,
49 }
50 }
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
55pub enum SystemColor {
56 Red,
57 Orange,
58 Yellow,
59 Green,
60 Mint,
61 Teal,
62 Cyan,
63 Blue,
64 Indigo,
65 Purple,
66 Pink,
67 Brown,
68}
69
70impl SystemColor {
71 pub const ALL: [Self; 12] = [
73 Self::Red,
74 Self::Orange,
75 Self::Yellow,
76 Self::Green,
77 Self::Mint,
78 Self::Teal,
79 Self::Cyan,
80 Self::Blue,
81 Self::Indigo,
82 Self::Purple,
83 Self::Pink,
84 Self::Brown,
85 ];
86
87 pub fn swatch(self) -> Swatch {
88 let (name, light, dark) = match self {
89 Self::Red => ("Red", 0xFF3B30, 0xFF453A),
90 Self::Orange => ("Orange", 0xFF9500, 0xFF9F0A),
91 Self::Yellow => ("Yellow", 0xFFCC00, 0xFFD60A),
92 Self::Green => ("Green", 0x28CD41, 0x32D74B),
93 Self::Mint => ("Mint", 0x00C7BE, 0x63E6E2),
94 Self::Teal => ("Teal", 0x59ADC4, 0x6AC4DC),
95 Self::Cyan => ("Cyan", 0x55BEF0, 0x5AC8F5),
96 Self::Blue => ("Blue", 0x007AFF, 0x0A84FF),
97 Self::Indigo => ("Indigo", 0x5856D6, 0x5E5CE6),
98 Self::Purple => ("Purple", 0xAF52DE, 0xBF5AF2),
99 Self::Pink => ("Pink", 0xFF2D55, 0xFF375F),
100 Self::Brown => ("Brown", 0xA2845E, 0xAC8E68),
101 };
102 Swatch::new(name, gpui::rgb(light), gpui::rgb(dark))
103 }
104
105 pub fn resolve(self, theme: &Theme) -> Hsla {
107 self.swatch().resolve(theme)
108 }
109
110 pub fn name(self) -> &'static str {
113 match self {
114 Self::Red => "red",
115 Self::Orange => "orange",
116 Self::Yellow => "yellow",
117 Self::Green => "green",
118 Self::Mint => "mint",
119 Self::Teal => "teal",
120 Self::Cyan => "cyan",
121 Self::Blue => "blue",
122 Self::Indigo => "indigo",
123 Self::Purple => "purple",
124 Self::Pink => "pink",
125 Self::Brown => "brown",
126 }
127 }
128
129 pub fn from_name(name: &str) -> Option<Self> {
130 Self::ALL.into_iter().find(|color| color.name() == name)
131 }
132}
133
134pub fn default_swatches() -> Rc<[Swatch]> {
136 SystemColor::ALL.map(SystemColor::swatch).into()
137}
138
139struct Swatches(Rc<[Swatch]>);
140
141impl Global for Swatches {}
142
143pub(crate) fn swatches(cx: &App) -> Rc<[Swatch]> {
144 cx.try_global::<Swatches>()
145 .map_or_else(default_swatches, |set| set.0.clone())
146}
147
148pub(crate) fn set_swatches(set: impl Into<Rc<[Swatch]>>, cx: &mut App) {
149 cx.set_global(Swatches(set.into()));
150 cx.refresh_windows();
151}