Skip to content

Commit 2c25886

Browse files
authored
feat: rewrite color (#98)
1 parent 810726e commit 2c25886

File tree

5 files changed

+110
-171
lines changed

5 files changed

+110
-171
lines changed

demo/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ leptos_devtools = { version = "0.0.1", optional = true}
1414
thaw = { path = "../thaw" }
1515
demo_markdown = { path = "../demo_markdown" }
1616
icondata = "0.3.0"
17+
palette = "0.7.4"
1718

1819
[features]
1920
default = ["csr"]
+27-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,38 @@
11
# Color Picker
22

33
```rust demo
4-
let value = create_rw_signal(RGBA::default());
4+
use palette::Srgb;
5+
6+
let value = create_rw_signal(Color::from(Srgb::new(0.0, 0.0, 0.0)));
57

68
view! {
79
<ColorPicker value/>
810
}
911
```
1012

13+
### Color Format
14+
15+
Encoding formats, support RGB, HSV, HSL.
16+
17+
```rust demo
18+
use palette::{Hsl, Hsv, Srgb};
19+
20+
let rgb = create_rw_signal(Color::from(Srgb::new(0.0, 0.0, 0.0)));
21+
let hsv = create_rw_signal(Color::from(Hsv::new(0.0, 0.0, 0.0)));
22+
let hsl = create_rw_signal(Color::from(Hsl::new(0.0, 0.0, 0.0)));
23+
24+
view! {
25+
<Space vertical=true>
26+
<ColorPicker value=rgb/>
27+
<ColorPicker value=hsv/>
28+
<ColorPicker value=hsl/>
29+
</Space>
30+
}
31+
```
32+
1133
### DatePicker Props
1234

13-
| Name | Type | Default | Desciption |
14-
| ----- | --------------------- | -------------------- | ----------------------------------------------- |
15-
| class | `MaybeSignal<String>` | `Default::default()` | Addtional classes for the color picker element. |
16-
| value | `RwSignal<RGBA>` | `Default::default()` | Value of the picker. |
35+
| Name | Type | Default | Desciption |
36+
| ----- | ----------------------------------- | -------------------- | ----------------------------------------------- |
37+
| class | `OptionalProp<MaybeSignal<String>>` | `Default::default()` | Addtional classes for the color picker element. |
38+
| value | `Model<Color>` | `Default::default()` | Value of the picker. |

thaw/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ icondata_ai = "0.0.10"
2727
uuid = { version = "1.7.0", features = ["v4"] }
2828
cfg-if = "1.0.0"
2929
chrono = "0.4.33"
30+
palette = "0.7.4"
3031

3132
[features]
3233
csr = ["leptos/csr"]

thaw/src/color_picker/color.rs

+17-145
Original file line numberDiff line numberDiff line change
@@ -1,160 +1,32 @@
1+
use palette::{Hsl, Hsv, Srgb};
2+
13
#[derive(Clone)]
2-
pub struct RGBA {
3-
pub red: u8,
4-
pub green: u8,
5-
pub blue: u8,
6-
pub alpha: u8,
4+
pub enum Color {
5+
RGB(Srgb),
6+
HSV(Hsv),
7+
HSL(Hsl),
78
}
89

9-
impl Default for RGBA {
10+
impl Default for Color {
1011
fn default() -> Self {
11-
Self {
12-
red: Default::default(),
13-
green: Default::default(),
14-
blue: Default::default(),
15-
alpha: u8::MAX,
16-
}
12+
Self::RGB(Srgb::new(0.0, 0.0, 0.0))
1713
}
1814
}
1915

20-
impl RGBA {
21-
pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
22-
Self {
23-
red: r,
24-
green: g,
25-
blue: b,
26-
alpha: a,
27-
}
28-
}
29-
30-
pub fn new_rgb(r: u8, g: u8, b: u8) -> Self {
31-
Self {
32-
red: r,
33-
green: g,
34-
blue: b,
35-
alpha: u8::MAX,
36-
}
37-
}
38-
39-
pub fn to_hex_string(&self) -> String {
40-
if self.alpha == u8::MAX {
41-
format!("#{:02X}{:02X}{:02X}", self.red, self.green, self.blue)
42-
} else {
43-
format!(
44-
"#{:02X}{:02X}{:02X}{:02X}",
45-
self.red, self.green, self.blue, self.alpha
46-
)
47-
}
16+
impl From<Srgb> for Color {
17+
fn from(value: Srgb) -> Self {
18+
Self::RGB(value)
4819
}
4920
}
5021

51-
impl From<HSV> for RGBA {
52-
fn from(value: HSV) -> Self {
53-
let HSV {
54-
hue: h,
55-
saturation: s,
56-
value: v,
57-
alpha,
58-
} = value;
59-
let h = f64::from(h);
60-
61-
let c = v * s;
62-
let x = c * (1.0 - f64::abs(((h / 60.0) % 2.0) - 1.0));
63-
let m = v - c;
64-
65-
let (r, g, b) = if (0.0..60.0).contains(&h) {
66-
(c, x, 0.0)
67-
} else if (60.0..120.0).contains(&h) {
68-
(x, c, 0.0)
69-
} else if (120.0..180.0).contains(&h) {
70-
(0.0, c, x)
71-
} else if (180.0..240.0).contains(&h) {
72-
(0.0, x, c)
73-
} else if (240.0..300.0).contains(&h) {
74-
(x, 0.0, c)
75-
} else if (300.0..360.0).contains(&h) {
76-
(c, 0.0, x)
77-
} else {
78-
(c, x, 0.0)
79-
};
80-
81-
let (r, g, b) = (
82-
((r + m) * 255.0) as u8,
83-
((g + m) * 255.0) as u8,
84-
((b + m) * 255.0) as u8,
85-
);
86-
87-
RGBA::new(r, g, b, alpha)
22+
impl From<Hsv> for Color {
23+
fn from(value: Hsv) -> Self {
24+
Self::HSV(value)
8825
}
8926
}
9027

91-
#[derive(Clone)]
92-
pub struct HSV {
93-
pub hue: u16,
94-
pub saturation: f64,
95-
pub value: f64,
96-
pub alpha: u8,
97-
}
98-
99-
impl HSV {
100-
pub fn new(hue: u16, saturation: f64, value: f64) -> Self {
101-
Self {
102-
hue,
103-
saturation,
104-
value,
105-
alpha: u8::MAX,
106-
}
107-
}
108-
109-
pub fn new_alpha(hue: u16, saturation: f64, value: f64, alpha: u8) -> Self {
110-
Self {
111-
hue,
112-
saturation,
113-
value,
114-
alpha,
115-
}
116-
}
117-
}
118-
119-
impl From<RGBA> for HSV {
120-
fn from(value: RGBA) -> Self {
121-
let RGBA {
122-
red: r,
123-
green: g,
124-
blue: b,
125-
alpha,
126-
} = value;
127-
128-
let (r, g, b) = (r as f64 / 255.0, g as f64 / 255.0, b as f64 / 255.0);
129-
130-
let c_max = f64::max(r, f64::max(g, b));
131-
let c_min = f64::min(r, f64::min(g, b));
132-
let delta = c_max - c_min;
133-
134-
let hue = if delta == 0.0 {
135-
0.0
136-
} else if c_max == r {
137-
60.0 * (((g - b) / delta) % 6.0)
138-
} else if c_max == g {
139-
60.0 * (((b - r) / delta) + 2.0)
140-
} else if c_max == b {
141-
60.0 * (((r - g) / delta) + 4.0)
142-
} else {
143-
unreachable!()
144-
};
145-
146-
let saturation = match c_max == 0.0 {
147-
true => 0.0,
148-
false => delta / c_max,
149-
};
150-
151-
let value = c_max;
152-
153-
HSV {
154-
hue: hue.to_string().parse().unwrap(),
155-
saturation,
156-
value,
157-
alpha,
158-
}
28+
impl From<Hsl> for Color {
29+
fn from(value: Hsl) -> Self {
30+
Self::HSL(value)
15931
}
16032
}

0 commit comments

Comments
 (0)