-
-
Notifications
You must be signed in to change notification settings - Fork 209
/
radialGradient.js
81 lines (75 loc) · 2.43 KB
/
radialGradient.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// @flow
/** */
type RadialGradientConfiguration = {
colorStops: Array<string>;
extent?: string;
fallback?: string;
position?: string;
shape?: string;
};
function parseFallback(colorStops: Array<string>) {
return colorStops[0].split(' ')[0]
}
function constructGradientValue(literals: Array<string>, ...substitutions: Array<string>) {
let template = ''
for (let i = 0; i < literals.length; i += 1) {
template += literals[i]
// Adds leading coma if properties preceed color-stops
if ((i === 3 && substitutions[i]) && (substitutions[0] || substitutions[1] || substitutions[2])) {
template = template.slice(0, -1)
template += `, ${substitutions[i]}`
// No trailing space if color-stops is the only param provided
} else if ((i === 3 && substitutions[i]) && (!substitutions[0] && !substitutions[1] && !substitutions[2])) {
template += `${substitutions[i]}`
// Only adds substitution if it is defined
} else if (substitutions[i]) {
template += `${substitutions[i]} `
}
}
return template.trim()
}
/**
* CSS for declaring a radial gradient, including a fallback background-color. The fallback is either the first color-stop or an explicitly passed fallback color.
*
* @example
* // Styles as object usage
* const styles = {
* ...radialGradient({
* colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],
* extent: 'farthest-corner at 45px 45px',
* position: 'center',
* shape: 'ellipse',
* })
* }
*
* // styled-components usage
* const div = styled.div`
* ${radialGradient({
* colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],
* extent: 'farthest-corner at 45px 45px',
* position: 'center',
* shape: 'ellipse',
* })}
*`
*
* // CSS as JS Output
*
* div: {
* 'background-color': '#00FFFF',
* 'background-image': 'radial-gradient(center ellipse farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%)',
* }
*/
function radialGradient({
colorStops,
extent,
fallback,
position,
shape,
}: RadialGradientConfiguration) {
if (!colorStops || colorStops.length < 2) throw new Error('radialGradient requries at least 2 color-stops to properly render.')
return {
'background-color': fallback || parseFallback(colorStops),
'background-image': constructGradientValue`radial-gradient(${position}${shape}${extent}${colorStops.join(', ')})`,
}
}
export default radialGradient