tangled
alpha
login
or
join now
quilling.dev
/
social-app
7
fork
atom
An ATproto social media client -- with an independent Appview.
7
fork
atom
overview
issues
pulls
pipelines
feat: convenience methods
serenity
6 months ago
1462e156
f963e0d8
+79
-21
2 changed files
expand all
collapse all
unified
split
src
alf
util
colors
conversion.ts
index.ts
+18
-21
src/alf/util/colors/conversion.ts
···
1
1
-
export interface HslColor {
2
2
-
h: number
3
3
-
s: number
4
4
-
l: number
5
5
-
}
6
6
-
7
7
-
export interface RgbColor {
8
8
-
r: number
9
9
-
g: number
10
10
-
b: number
11
11
-
}
12
12
-
13
13
-
export type HexCode = `#${string}` | string
1
1
+
import {type HexCode, type HslColor, type RgbColor} from '#/alf/util/colors'
14
2
15
3
/**
16
4
* Converts a hexcode string in the format `"#RRGGBB"` to a `HslColor` object (`{ h: number, s: number, l: number }`).
···
23
11
const r = parseInt(hex.substring(0, 2), 16) / 255
24
12
const g = parseInt(hex.substring(2, 4), 16) / 255
25
13
const b = parseInt(hex.substring(4, 6), 16) / 255
14
14
+
const a = hex.length > 6 ? parseInt(hex.substring(6, 8), 16) / 255 : undefined
26
15
27
16
const max = Math.max(r, g, b)
28
17
const min = Math.min(r, g, b)
···
57
46
h: h * 360,
58
47
s: s * 100,
59
48
l: l * 100,
49
49
+
a,
60
50
}
61
51
}
62
52
···
67
57
* @returns {HexCode} A hexcode string in the format `"#RRGGBB"`. The leading "#" symbol is optional.
68
58
*/
69
59
export const hslToHex = (
70
70
-
{h, s, l}: HslColor,
60
60
+
{h, s, l, a}: HslColor,
71
61
appendSymbol: boolean = true,
72
62
): HexCode => {
73
63
h = (h % 360) / 360
···
103
93
const g = hue(h) * 255
104
94
const b = hue(h - 1 / 3) * 255
105
95
106
106
-
return `${appendSymbol ? '#' : ''}${r.toString(16)}${g.toString(16)}${b.toString(16)}`
96
96
+
return `${appendSymbol ? '#' : ''}${r.toString(16)}${g.toString(16)}${b.toString(16)}${a ? a.toString(16) : ''}`
107
97
}
108
98
109
99
/**
···
113
103
* @returns {HexCode} A hexcode string in the format `"#RRGGBB"`. The leading "#" symbol is optional.
114
104
*/
115
105
export const rgbToHex = (
116
116
-
{r, g, b}: RgbColor,
106
106
+
{r, g, b, a}: RgbColor,
117
107
appendSymbol: boolean = true,
118
108
): HexCode => {
119
119
-
return `${appendSymbol ? '#' : ''}${r.toString(16)}${g.toString(16)}${b.toString(16)}`
109
109
+
return `${appendSymbol ? '#' : ''}${r.toString(16)}${g.toString(16)}${b.toString(16)}${a ? a.toString(16) : ''}`
120
110
}
121
111
122
112
/**
···
129
119
const r = parseInt(hex.substring(0, 2), 16) / 255
130
120
const g = parseInt(hex.substring(2, 4), 16) / 255
131
121
const b = parseInt(hex.substring(4, 6), 16) / 255
132
132
-
return {r, g, b}
122
122
+
const a = hex.length > 6 ? parseInt(hex.substring(6, 8), 16) / 255 : undefined
123
123
+
return {r, g, b, a}
133
124
}
134
125
135
126
/**
···
137
128
* @param {RgbColor} - An RGB colour object.
138
129
* @returns {HslColor} A HSL colour object.
139
130
*/
140
140
-
export const rgbToHsl = ({r, g, b}: RgbColor): HslColor => {
131
131
+
export const rgbToHsl = ({r, g, b, a}: RgbColor): HslColor => {
141
132
r = r / 255
142
133
g = g / 255
143
134
b = b / 255
···
174
165
h: h * 360,
175
166
s: s * 100,
176
167
l: l * 100,
168
168
+
a: a ? (a / 255) * 100 : undefined,
177
169
}
178
170
}
179
171
···
182
174
* @param {HslColor} - A HSL colour object.
183
175
* @returns {RgbColor} An RGB colour object.
184
176
*/
185
185
-
export const hslToRgb = ({h, s, l}: HslColor): RgbColor => {
177
177
+
export const hslToRgb = ({h, s, l, a}: HslColor): RgbColor => {
186
178
h = (h % 360) / 360
187
179
s = Math.max(0, Math.min(1, s / 100))
188
180
l = Math.max(0, Math.min(1, l / 100))
···
216
208
const g = hue(h) * 255
217
209
const b = hue(h - 1 / 3) * 255
218
210
219
219
-
return {r: Math.round(r), g: Math.round(g), b: Math.round(b)}
211
211
+
return {
212
212
+
r: Math.round(r),
213
213
+
g: Math.round(g),
214
214
+
b: Math.round(b),
215
215
+
a: a ? (a / 100) * 255 : undefined,
216
216
+
}
220
217
}
+61
src/alf/util/colors/index.ts
···
1
1
+
import {hexToHsl, hslToHex} from '#/alf/util/colors/conversion'
2
2
+
3
3
+
export interface HslColor {
4
4
+
h: number
5
5
+
s: number
6
6
+
l: number
7
7
+
a?: number
8
8
+
}
9
9
+
10
10
+
export interface RgbColor {
11
11
+
r: number
12
12
+
g: number
13
13
+
b: number
14
14
+
a?: number
15
15
+
}
16
16
+
17
17
+
export type HexCode = `#${string}` | string
18
18
+
19
19
+
export const clamp = (val: number) => {
20
20
+
return Math.min(1, Math.max(0, val))
21
21
+
}
22
22
+
23
23
+
export const lighten = (
24
24
+
hex: HexCode,
25
25
+
amount: number,
26
26
+
method: 'relative' | undefined = undefined,
27
27
+
) => {
28
28
+
const hsl = hexToHsl(hex)
29
29
+
30
30
+
if (typeof method !== 'undefined' && method === 'relative') {
31
31
+
hsl.l += (hsl.l * amount) / 100
32
32
+
} else {
33
33
+
hsl.l += amount / 100
34
34
+
}
35
35
+
hsl.l = clamp(hsl.l)
36
36
+
return hslToHex(hsl)
37
37
+
}
38
38
+
39
39
+
export const darken = (
40
40
+
hex: HexCode,
41
41
+
amount: number,
42
42
+
method: 'relative' | undefined = undefined,
43
43
+
) => {
44
44
+
const hsl = hexToHsl(hex)
45
45
+
46
46
+
if (typeof method !== 'undefined' && method === 'relative') {
47
47
+
hsl.l -= (hsl.l * amount) / 100
48
48
+
} else {
49
49
+
hsl.l -= amount / 100
50
50
+
}
51
51
+
hsl.l = clamp(hsl.l)
52
52
+
return hslToHex(hsl)
53
53
+
}
54
54
+
55
55
+
export const fade = (hex: HexCode, amount: number) => {
56
56
+
const hsl = hexToHsl(hex)
57
57
+
58
58
+
hsl.a = amount / 100
59
59
+
hsl.a = clamp(hsl.a)
60
60
+
return hslToHex(hsl)
61
61
+
}