Skip to content

Commit 97f0708

Browse files
ColorName tool (#686)
* Adding ColorName tool * Adding accessibility label using ColorName tool to ColorSwatch component * removing system colors from map * pr comments * lint fix Co-authored-by: Ethan Sharabi <ethans@wix.com>
1 parent cbd661f commit 97f0708

File tree

7 files changed

+1740
-1
lines changed

7 files changed

+1740
-1
lines changed

demo/src/screens/componentScreens/ColorPickerScreen.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _ from 'lodash';
22
import React, {Component} from 'react';
33
import {StyleSheet, ScrollView} from 'react-native';
4-
import {Colors, View, Text, ColorPicker, ColorPalette} from 'react-native-ui-lib';
4+
import {Colors, View, Text, ColorPicker, ColorPalette, ColorName} from 'react-native-ui-lib';
55

66

77
const INITIAL_COLOR = Colors.blue30;
@@ -52,6 +52,11 @@ export default class ColorPickerScreen extends Component {
5252
const paletteValue = paletteChange ? (color || INITIAL_COLOR) : undefined;
5353
const pickerValue = !paletteChange ? (color || INITIAL_COLOR) : undefined;
5454

55+
const mappedColor = ColorName.name(color);
56+
const nearestColor = mappedColor[0];
57+
const colorName = mappedColor[1];
58+
const isMapped = mappedColor[2] ? 'Mapped' : 'Not mapped';
59+
5560
return (
5661
<ScrollView style={styles.container} contentContainerStyle={{paddingBottom: 20}}>
5762
<View center bg-white marginV-10>
@@ -75,6 +80,15 @@ export default class ColorPickerScreen extends Component {
7580
// animatedIndex={0}
7681
/>
7782
</View>
83+
84+
<View marginV-10 bg-white>
85+
<Text center text60 marginT-10>Color Name</Text>
86+
<View spread row margin-10 style={{backgroundColor: nearestColor}}>
87+
<Text margin-5 text70 style={{color: textColor}}>{nearestColor}</Text>
88+
<Text margin-5 text60 style={{color: textColor}}>{colorName}</Text>
89+
<Text margin-5 text70 style={{color: textColor}}>{isMapped}</Text>
90+
</View>
91+
</View>
7892
</ScrollView>
7993
);
8094
}

src/components/colorPicker/ColorSwatch.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export default class ColorSwatch extends PureBaseComponent {
143143
onPress={this.onPress}
144144
style={[this.styles.container, style]}
145145
onLayout={this.onLayout}
146+
accessibilityLabel={Colors.getColorName(color)}
146147
>
147148
{Colors.isTransparent(color) && (
148149
<Image source={transparentImage} style={this.styles.transparentImage} resizeMode={'cover'}/>

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ module.exports = {
233233
get Colors() {
234234
return require('./style').Colors;
235235
},
236+
get ColorName() {
237+
return require('./style').ColorName;
238+
},
236239
get BorderRadiuses() {
237240
return require('./style').BorderRadiuses;
238241
},

src/style/colorName.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// adopted from: ntc js (Name that Color JavaScript)
2+
// http://chir.ag/projects/ntc
3+
4+
const names = require('./colorNameMap').colorNameMap;
5+
6+
// ColorName.name(hex_color) will return array for nearest color: ['hex color', 'color name', isMapped]
7+
class ColorName {
8+
_init() {
9+
let color;
10+
let rgb;
11+
let hsl;
12+
13+
for (let i = 0; i < names.length; i++) {
14+
color = '#' + names[i][0];
15+
rgb = this._rgb(color);
16+
hsl = this._hsl(color);
17+
names[i].push(rgb[0], rgb[1], rgb[2], hsl[0], hsl[1], hsl[2]);
18+
}
19+
}
20+
21+
name(color) {
22+
color = color.toUpperCase();
23+
if (color.length < 3 || color.length > 7) {
24+
return ['#000000', 'Invalid Color: ' + color, false];
25+
}
26+
if (color.length % 3 === 0) {
27+
color = '#' + color;
28+
}
29+
if (color.length === 4) {
30+
color = '#' + color.substr(1, 1) + color.substr(1, 1) + color.substr(2, 1) + color.substr(2, 1) + color.substr(3, 1) + color.substr(3, 1);
31+
}
32+
33+
const rgb = this._rgb(color);
34+
const r = rgb[0];
35+
const g = rgb[1];
36+
const b = rgb[2];
37+
38+
const hsl = this._hsl(color);
39+
const h = hsl[0];
40+
const s = hsl[1];
41+
const l = hsl[2];
42+
43+
let ndf1 = 0;
44+
let ndf2 = 0;
45+
let ndf = 0;
46+
47+
let cl = -1;
48+
let df = -1;
49+
50+
for (let i = 0; i < names.length; i++) {
51+
if (color === '#' + names[i][0]) {
52+
return ['#' + names[i][0], names[i][1], true];
53+
}
54+
55+
ndf1 = Math.pow(r - names[i][2], 2) + Math.pow(g - names[i][3], 2) + Math.pow(b - names[i][4], 2);
56+
ndf2 = Math.pow(h - names[i][5], 2) + Math.pow(s - names[i][6], 2) + Math.pow(l - names[i][7], 2);
57+
ndf = ndf1 + ndf2 * 2;
58+
59+
if (df < 0 || df > ndf) {
60+
df = ndf;
61+
cl = i;
62+
}
63+
}
64+
65+
return (cl < 0 ? ['#000000', 'Invalid Color: ' + color, false] : ['#' + names[cl][0], names[cl][1], false]);
66+
}
67+
68+
// adopted from: Farbtastic 1.2
69+
// http://acko.net/dev/farbtastic
70+
_hsl(color) {
71+
const rgb = [
72+
parseInt('0x' + color.substring(1, 3)) / 255,
73+
parseInt('0x' + color.substring(3, 5)) / 255,
74+
parseInt('0x' + color.substring(5, 7)) / 255
75+
];
76+
const r = rgb[0];
77+
const g = rgb[1];
78+
const b = rgb[2];
79+
80+
const min = Math.min(r, Math.min(g, b));
81+
const max = Math.max(r, Math.max(g, b));
82+
const delta = max - min;
83+
const l = (min + max) / 2;
84+
85+
let s = 0;
86+
if (l > 0 && l < 1) {
87+
s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
88+
}
89+
90+
let h = 0;
91+
if (delta > 0) {
92+
if (max === r && max !== g) {
93+
h += (g - b) / delta;
94+
}
95+
if (max === g && max !== b) {
96+
h += (2 + (b - r) / delta);
97+
}
98+
if (max === b && max !== r) {
99+
h += (4 + (r - g) / delta);
100+
}
101+
h /= 6;
102+
}
103+
104+
return [
105+
parseInt(h * 255),
106+
parseInt(s * 255),
107+
parseInt(l * 255)
108+
];
109+
}
110+
111+
// adopted from: Farbtastic 1.2
112+
// http://acko.net/dev/farbtastic
113+
_rgb(color) {
114+
return [
115+
parseInt('0x' + color.substring(1, 3)),
116+
parseInt('0x' + color.substring(3, 5)),
117+
parseInt('0x' + color.substring(5, 7))
118+
];
119+
}
120+
}
121+
122+
const object = new ColorName();
123+
object._init();
124+
125+
export default object;

0 commit comments

Comments
 (0)