Skip to content

Commit

Permalink
ColorName tool (#686)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
Inbal-Tish and ethanshar authored Mar 8, 2020
1 parent cbd661f commit 97f0708
Show file tree
Hide file tree
Showing 7 changed files with 1,740 additions and 1 deletion.
16 changes: 15 additions & 1 deletion demo/src/screens/componentScreens/ColorPickerScreen.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'lodash';
import React, {Component} from 'react';
import {StyleSheet, ScrollView} from 'react-native';
import {Colors, View, Text, ColorPicker, ColorPalette} from 'react-native-ui-lib';
import {Colors, View, Text, ColorPicker, ColorPalette, ColorName} from 'react-native-ui-lib';


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

const mappedColor = ColorName.name(color);
const nearestColor = mappedColor[0];
const colorName = mappedColor[1];
const isMapped = mappedColor[2] ? 'Mapped' : 'Not mapped';

return (
<ScrollView style={styles.container} contentContainerStyle={{paddingBottom: 20}}>
<View center bg-white marginV-10>
Expand All @@ -75,6 +80,15 @@ export default class ColorPickerScreen extends Component {
// animatedIndex={0}
/>
</View>

<View marginV-10 bg-white>
<Text center text60 marginT-10>Color Name</Text>
<View spread row margin-10 style={{backgroundColor: nearestColor}}>
<Text margin-5 text70 style={{color: textColor}}>{nearestColor}</Text>
<Text margin-5 text60 style={{color: textColor}}>{colorName}</Text>
<Text margin-5 text70 style={{color: textColor}}>{isMapped}</Text>
</View>
</View>
</ScrollView>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/components/colorPicker/ColorSwatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export default class ColorSwatch extends PureBaseComponent {
onPress={this.onPress}
style={[this.styles.container, style]}
onLayout={this.onLayout}
accessibilityLabel={Colors.getColorName(color)}
>
{Colors.isTransparent(color) && (
<Image source={transparentImage} style={this.styles.transparentImage} resizeMode={'cover'}/>
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ module.exports = {
get Colors() {
return require('./style').Colors;
},
get ColorName() {
return require('./style').ColorName;
},
get BorderRadiuses() {
return require('./style').BorderRadiuses;
},
Expand Down
125 changes: 125 additions & 0 deletions src/style/colorName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// adopted from: ntc js (Name that Color JavaScript)
// http://chir.ag/projects/ntc

const names = require('./colorNameMap').colorNameMap;

// ColorName.name(hex_color) will return array for nearest color: ['hex color', 'color name', isMapped]
class ColorName {
_init() {
let color;
let rgb;
let hsl;

for (let i = 0; i < names.length; i++) {
color = '#' + names[i][0];
rgb = this._rgb(color);
hsl = this._hsl(color);
names[i].push(rgb[0], rgb[1], rgb[2], hsl[0], hsl[1], hsl[2]);
}
}

name(color) {
color = color.toUpperCase();
if (color.length < 3 || color.length > 7) {
return ['#000000', 'Invalid Color: ' + color, false];
}
if (color.length % 3 === 0) {
color = '#' + color;
}
if (color.length === 4) {
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);
}

const rgb = this._rgb(color);
const r = rgb[0];
const g = rgb[1];
const b = rgb[2];

const hsl = this._hsl(color);
const h = hsl[0];
const s = hsl[1];
const l = hsl[2];

let ndf1 = 0;
let ndf2 = 0;
let ndf = 0;

let cl = -1;
let df = -1;

for (let i = 0; i < names.length; i++) {
if (color === '#' + names[i][0]) {
return ['#' + names[i][0], names[i][1], true];
}

ndf1 = Math.pow(r - names[i][2], 2) + Math.pow(g - names[i][3], 2) + Math.pow(b - names[i][4], 2);
ndf2 = Math.pow(h - names[i][5], 2) + Math.pow(s - names[i][6], 2) + Math.pow(l - names[i][7], 2);
ndf = ndf1 + ndf2 * 2;

if (df < 0 || df > ndf) {
df = ndf;
cl = i;
}
}

return (cl < 0 ? ['#000000', 'Invalid Color: ' + color, false] : ['#' + names[cl][0], names[cl][1], false]);
}

// adopted from: Farbtastic 1.2
// http://acko.net/dev/farbtastic
_hsl(color) {
const rgb = [
parseInt('0x' + color.substring(1, 3)) / 255,
parseInt('0x' + color.substring(3, 5)) / 255,
parseInt('0x' + color.substring(5, 7)) / 255
];
const r = rgb[0];
const g = rgb[1];
const b = rgb[2];

const min = Math.min(r, Math.min(g, b));
const max = Math.max(r, Math.max(g, b));
const delta = max - min;
const l = (min + max) / 2;

let s = 0;
if (l > 0 && l < 1) {
s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
}

let h = 0;
if (delta > 0) {
if (max === r && max !== g) {
h += (g - b) / delta;
}
if (max === g && max !== b) {
h += (2 + (b - r) / delta);
}
if (max === b && max !== r) {
h += (4 + (r - g) / delta);
}
h /= 6;
}

return [
parseInt(h * 255),
parseInt(s * 255),
parseInt(l * 255)
];
}

// adopted from: Farbtastic 1.2
// http://acko.net/dev/farbtastic
_rgb(color) {
return [
parseInt('0x' + color.substring(1, 3)),
parseInt('0x' + color.substring(3, 5)),
parseInt('0x' + color.substring(5, 7))
];
}
}

const object = new ColorName();
object._init();

export default object;
Loading

0 comments on commit 97f0708

Please sign in to comment.