Skip to content

Commit 9bfc567

Browse files
Guilherme Montegmonte
Guilherme Monte
authored andcommitted
feat: added recommended colors array
1 parent 5a7ae27 commit 9bfc567

17 files changed

+1137
-10
lines changed

.history/index.d_20230205171518.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Component } from 'react';
2+
3+
export class Color {
4+
h: number;
5+
s: number;
6+
v: number;
7+
r: number;
8+
g: number;
9+
b: number;
10+
a: number;
11+
hex: string;
12+
rgba: string;
13+
}
14+
15+
export interface InputColorProps {
16+
initialValue: string;
17+
placement?: string;
18+
onChange?(color: Color): void;
19+
disabled?: boolean;
20+
}
21+
22+
export default function InputColor(props: InputColorProps);

.history/index.d_20230205183030.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Component } from 'react';
2+
3+
export class Color {
4+
h: number;
5+
s: number;
6+
v: number;
7+
r: number;
8+
g: number;
9+
b: number;
10+
a: number;
11+
hex: string;
12+
rgba: string;
13+
}
14+
15+
export interface InputColorProps {
16+
initialValue: string;
17+
placement?: string;
18+
onChange?(color: Color): void;
19+
disabled?: boolean;
20+
recommendedColors?: string[];
21+
}
22+
23+
export default function InputColor(props: InputColorProps);
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
/** @jsx jsx */
2+
import { jsx } from '@emotion/core';
3+
import InputSlider from 'react-input-slider';
4+
import InputNumber from 'react-input-number';
5+
import {
6+
rgb2hsv,
7+
hsv2hex,
8+
rgb2hex,
9+
hex2rgb,
10+
rgba,
11+
hsv2rgb,
12+
} from '@swiftcarrot/color-fns';
13+
import { rgba2hex, parseColor, onlyUnique } from './utils';
14+
import ColorSquare from './color-square'
15+
16+
const KEY_ENTER = 13;
17+
18+
const ColorPicker = ({ color, onChange, disabled, recommendedColors }) => {
19+
const { r, g, b, a, h, s, v } = color;
20+
21+
function changeColor(color) {
22+
if (onChange) {
23+
onChange({
24+
...color,
25+
rgba: rgba(color.r, color.g, color.b, color.a),
26+
hex: rgba2hex(color.r, color.g, color.b, color.a),
27+
});
28+
}
29+
}
30+
31+
function changeHSV(h, s, v) {
32+
const { r, g, b } = hsv2rgb(h, s, v);
33+
const hex = rgb2hex(r, g, b);
34+
changeColor({ ...color, h, s, v, r, g, b, hex });
35+
}
36+
37+
function changeRGB(r, g, b) {
38+
const hex = rgb2hex(r, g, b);
39+
const { h, s, v } = rgb2hsv(r, g, b);
40+
changeColor({ ...color, r, g, b, h, s, v, hex });
41+
}
42+
43+
function changeAlpha(a) {
44+
changeColor({ ...color, a });
45+
}
46+
47+
function changeHex(hex) {
48+
const { r, g, b } = hex2rgb(hex);
49+
const { h, s, v } = rgb2hsv(r, g, b);
50+
changeColor({ ...color, r, g, b, h, s, v, hex });
51+
}
52+
53+
function handleHexKeyUp(e) {
54+
if (e.keyCode === KEY_ENTER) {
55+
const hex = e.target.value.trim();
56+
const { r, g, b } = hex2rgb(hex);
57+
changeColor({ ...color, r, g, b, a, hex });
58+
}
59+
}
60+
61+
function handleClick(e) {
62+
e.stopPropagation();
63+
e.nativeEvent.stopImmediatePropagation();
64+
}
65+
66+
const rgbaBackground = rgba(r, g, b, a);
67+
const rgba0 = rgba(r, g, b, 0);
68+
const rgba100 = rgba(r, g, b, 100);
69+
const opacityGradient = `linear-gradient(to right, ${rgba0}, ${rgba100})`;
70+
const hueBackground = hsv2hex(h, 100, 100);
71+
72+
return (
73+
<div css={styles.picker} onClick={handleClick}>
74+
75+
{recommendedColors.length && (
76+
<div css={styles.recommendedColors}>
77+
{recommendedColors.filter(onlyUnique).map((recommendedColor) => (
78+
<ColorSquare
79+
key={recommendedColor}
80+
color={recommendedColor}
81+
onClick={() => !disabled && onChange(parseColor(recommendedColor))}
82+
disabled={disabled}
83+
/>
84+
))}
85+
</div>
86+
)}
87+
88+
<div css={styles.selector} style={{ backgroundColor: hueBackground }}>
89+
<div css={styles.gradientWhite} />
90+
<div css={styles.gradientDark} />
91+
<InputSlider
92+
axis="xy"
93+
x={s}
94+
xmax={100}
95+
y={100 - v}
96+
ymax={100}
97+
onChange={({ x, y }) => changeHSV(h, x, 100 - y)}
98+
disabled={disabled}
99+
styles={{
100+
track: { width: '100%', height: '100%', background: 'none' },
101+
thumb: {
102+
width: 12,
103+
height: 12,
104+
backgroundColor: 'rgba(0,0,0,0)',
105+
border: '2px solid #fff',
106+
borderRadius: '50%',
107+
},
108+
}}
109+
/>
110+
</div>
111+
112+
<div
113+
css={{
114+
width: '100%',
115+
marginTop: 10,
116+
marginBottom: 10,
117+
display: 'flex',
118+
}}
119+
>
120+
<div css={{ flex: 1, marginRight: 10 }}>
121+
<InputSlider
122+
axis="x"
123+
x={h}
124+
xmax={359}
125+
onChange={({ x }) => changeHSV(x, s, v)}
126+
disabled={disabled}
127+
styles={{
128+
track: {
129+
width: '100%',
130+
height: 12,
131+
borderRadius: 0,
132+
background:
133+
'linear-gradient(to left, #FF0000 0%, #FF0099 10%, #CD00FF 20%, #3200FF 30%, #0066FF 40%, #00FFFD 50%, #00FF66 60%, #35FF00 70%, #CDFF00 80%, #FF9900 90%, #FF0000 100%)',
134+
},
135+
active: {
136+
background: 'none',
137+
},
138+
thumb: {
139+
width: 5,
140+
height: 14,
141+
borderRadius: 0,
142+
backgroundColor: '#eee',
143+
},
144+
}}
145+
/>
146+
<InputSlider
147+
axis="x"
148+
x={a}
149+
xmax={100}
150+
styles={{
151+
track: {
152+
width: '100%',
153+
height: 12,
154+
borderRadius: 0,
155+
background: opacityGradient,
156+
},
157+
active: {
158+
background: 'none',
159+
},
160+
thumb: {
161+
width: 5,
162+
height: 14,
163+
borderRadius: 0,
164+
backgroundColor: '#eee',
165+
},
166+
}}
167+
onChange={({ x }) => changeAlpha(x)}
168+
disabled={disabled}
169+
/>
170+
</div>
171+
<ColorSquare color={rgbaBackground} />
172+
</div>
173+
174+
<div css={styles.inputs}>
175+
<div css={styles.input}>
176+
<input
177+
style={{ width: 70, textAlign: 'left' }}
178+
type="text"
179+
value={color.hex}
180+
onChange={(e) => changeHex(e.target.value)}
181+
onKeyUp={handleHexKeyUp}
182+
disabled={disabled}
183+
/>
184+
<div>Hex</div>
185+
</div>
186+
187+
<div css={styles.input}>
188+
<InputNumber
189+
min={0}
190+
max={255}
191+
value={r}
192+
onChange={(r) => changeRGB(r, g, b)}
193+
disabled={disabled}
194+
/>
195+
<div>R</div>
196+
</div>
197+
<div css={styles.input}>
198+
<InputNumber
199+
min={0}
200+
max={255}
201+
value={g}
202+
onChange={(g) => changeRGB(r, g, b)}
203+
disabled={disabled}
204+
/>
205+
<div>G</div>
206+
</div>
207+
<div css={styles.input}>
208+
<InputNumber
209+
min={0}
210+
max={255}
211+
value={b}
212+
onChange={(b) => changeRGB(r, g, b)}
213+
disabled={disabled}
214+
/>
215+
<div>B</div>
216+
</div>
217+
218+
<div css={styles.input}>
219+
<InputNumber
220+
min={0}
221+
max={100}
222+
value={a}
223+
onChange={(a) => changeAlpha(a)}
224+
disabled={disabled}
225+
/>
226+
<div>A</div>
227+
</div>
228+
</div>
229+
</div>
230+
);
231+
};
232+
233+
ColorPicker.defaultProps = {
234+
initialValue: '#5e72e4',
235+
disabled: false,
236+
recommendedColors: []
237+
};
238+
239+
const styles = {
240+
picker: {
241+
fontFamily: `'Helvetica Neue',Helvetica,Arial,sans-serif`,
242+
width: 230,
243+
244+
'*': {
245+
userSelect: 'none',
246+
},
247+
},
248+
249+
selector: {
250+
position: 'relative',
251+
width: 230,
252+
height: 230,
253+
},
254+
255+
gradientWhite: {
256+
position: 'absolute',
257+
top: 0,
258+
left: 0,
259+
right: 0,
260+
bottom: 0,
261+
background:
262+
'linear-gradient(to right, #ffffff 0%, rgba(255, 255, 255, 0) 100%)',
263+
},
264+
265+
gradientDark: {
266+
position: 'absolute',
267+
top: 0,
268+
left: 0,
269+
right: 0,
270+
bottom: 0,
271+
background: 'linear-gradient(to bottom, transparent 0%, #000000 100%)',
272+
},
273+
274+
inputs: {
275+
display: 'flex',
276+
justifyContent: 'space-between',
277+
width: '100%',
278+
},
279+
280+
input: {
281+
textAlign: 'center',
282+
fontSize: 13,
283+
fontWeight: 'normal',
284+
color: '#000',
285+
286+
input: {
287+
width: 30,
288+
textAlign: 'center',
289+
},
290+
291+
div: {
292+
marginTop: 4,
293+
},
294+
},
295+
296+
recommendedColors: {
297+
width: '100%',
298+
display: 'flex',
299+
flexWrap: 'wrap',
300+
alignItems: 'center',
301+
paddingBottom: 10,
302+
marginBottom: 10,
303+
borderBottom: '1px solid #e9e9e9'
304+
}
305+
};
306+
307+
export default ColorPicker;

0 commit comments

Comments
 (0)