Skip to content

Commit

Permalink
Merge pull request #53 from levibuzolic/normalize-colors
Browse files Browse the repository at this point in the history
Normalize all colors that React Native supports
  • Loading branch information
jpudysz authored Oct 31, 2023
2 parents 8653436 + 3796d36 commit 92c3f5d
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 67 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"devDependencies": {
"@commitlint/config-conventional": "17.8.0",
"@react-native/eslint-config": "0.74.0",
"@react-native/normalize-colors": "0.74.1",
"@release-it/conventional-changelog": "5.1.1",
"@testing-library/react-hooks": "8.0.1",
"@types/jest": "29.5.5",
Expand Down Expand Up @@ -75,6 +76,7 @@
"typescript": "5.2.2"
},
"peerDependencies": {
"@react-native/normalize-colors": "*",
"react": "*",
"react-native": "*",
"react-native-web": "*"
Expand Down
126 changes: 82 additions & 44 deletions src/__tests__/normalizer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,26 @@ describe('Normalizer', () => {
height: -10
},
shadowOpacity: 0.5
},
{
shadowRadius: 3,
shadowColor: 'blue',
shadowOffset: {
width: 0,
height: -10
},
shadowOpacity: 0.5
}
]
const results: Array<string> = [
'3px 2px 3px rgba(0,0,0,0.4)',
'0 0 1px rgba(171,202,188,1)',
'0 0 1px #abcabc',
'0 1px 0 rgba(127,17,224,0.3)',
'-4px -3px 3px rgba(255,87,51,0.5)',
'0 0 0 rgba(0,0,0,0)',
'50px 50px 20px orange',
'0 -10px 3px rgba(255,87,51,0.8)'
'0 -10px 3px rgba(255,87,51,0.4)',
'0 -10px 3px rgba(0,0,255,0.5)'
]

styles.forEach((style, index) => {
Expand Down Expand Up @@ -131,11 +141,11 @@ describe('Normalizer', () => {
}
]
const results: Array<string> = [
'4px 5px 2px rgba(255,255,255,1)',
'3px 4px 5px rgba(0,0,0,1)',
'-1px -1px 0 rgba(255,87,51,1)',
'4px 5px 2px #fff',
'3px 4px 5px #000000',
'-1px -1px 0 #FF5733',
'0 0 0 red',
'-5px -5px 0 rgba(255,87,51,0.8)'
'-5px -5px 0 #FF5733CC'
]

styles.forEach((style, index) => {
Expand Down Expand Up @@ -237,17 +247,45 @@ describe('Normalizer', () => {
})

describe('normalizeColor', () => {
it('should not normalize string colors', () => {
it('should not normalize string colors when no opacity is defined', () => {
const values: Array<string> = [
'red',
'orange',
'pink',
'purple',
'black'
]
const results: Array<string> = [
'red',
'orange',
'pink',
'purple',
'black'
]

values.forEach((value, index) => {
expect(normalizeColor(value)).toEqual(values[index])
expect(normalizeColor(value)).toEqual(results[index])
})
})

it('should normalize string colors when opacity is defined', () => {
const values: Array<string> = [
'red',
'orange',
'pink',
'purple',
'black'
]
const results: Array<string> = [
'rgba(255,0,0,0.5)',
'rgba(255,165,0,0.5)',
'rgba(255,192,203,0.5)',
'rgba(128,0,128,0.5)',
'rgba(0,0,0,0.5)'
]

values.forEach((value, index) => {
expect(normalizeColor(value, 0.5)).toEqual(results[index])
})
})

Expand All @@ -265,20 +303,20 @@ describe('Normalizer', () => {
'#456'
]
const results: Array<string> = [
'rgba(255,0,0,1)',
'rgba(0,255,0,1)',
'rgba(0,0,255,1)',
'rgba(255,255,0,1)',
'rgba(255,0,255,1)',
'rgba(0,255,255,1)',
'rgba(255,255,255,1)',
'rgba(170,187,204,1)',
'rgba(17,34,51,1)',
'rgba(68,85,102,1)'
'rgba(255,0,0,0.2)',
'rgba(0,255,0,0.2)',
'rgba(0,0,255,0.2)',
'rgba(255,255,0,0.2)',
'rgba(255,0,255,0.2)',
'rgba(0,255,255,0.2)',
'rgba(255,255,255,0.2)',
'rgba(170,187,204,0.2)',
'rgba(17,34,51,0.2)',
'rgba(68,85,102,0.2)'
]

values.forEach((value, index) => {
expect(normalizeColor(value)).toEqual(results[index])
expect(normalizeColor(value, 0.2)).toEqual(results[index])
})
})

Expand All @@ -296,20 +334,20 @@ describe('Normalizer', () => {
'#445566'
]
const results: Array<string> = [
'rgba(255,0,0,1)',
'rgba(0,255,0,1)',
'rgba(0,0,255,1)',
'rgba(255,255,0,1)',
'rgba(255,0,255,1)',
'rgba(0,255,255,1)',
'rgba(255,255,255,1)',
'rgba(170,187,204,1)',
'rgba(17,34,51,1)',
'rgba(68,85,102,1)'
'rgba(255,0,0,0.99)',
'rgba(0,255,0,0.99)',
'rgba(0,0,255,0.99)',
'rgba(255,255,0,0.99)',
'rgba(255,0,255,0.99)',
'rgba(0,255,255,0.99)',
'rgba(255,255,255,0.99)',
'rgba(170,187,204,0.99)',
'rgba(17,34,51,0.99)',
'rgba(68,85,102,0.99)'
]

values.forEach((value, index) => {
expect(normalizeColor(value)).toEqual(results[index])
expect(normalizeColor(value, 0.99)).toEqual(results[index])
})
})

Expand All @@ -327,20 +365,20 @@ describe('Normalizer', () => {
'#44556677'
]
const results: Array<string> = [
'rgba(255,0,0,1)',
'rgba(0,255,0,1)',
'rgba(0,0,255,1)',
'rgba(255,255,0,1)',
'rgba(255,0,255,1)',
'rgba(0,255,255,1)',
'rgba(255,255,255,1)',
'rgba(170,187,204,0.8666666666666667)',
'rgba(17,34,51,0.26666666666666666)',
'rgba(68,85,102,0.4666666666666667)'
'rgba(255,0,0,0.1)',
'rgba(0,255,0,0.1)',
'rgba(0,0,255,0.1)',
'rgba(255,255,0,0.1)',
'rgba(255,0,255,0.1)',
'rgba(0,255,255,0.1)',
'rgba(255,255,255,0.1)',
'rgba(170,187,204,0.08666666666666667)',
'rgba(17,34,51,0.02666666666666667)',
'rgba(68,85,102,0.04666666666666667)'
]

values.forEach((value, index) => {
expect(normalizeColor(value)).toEqual(results[index])
expect(normalizeColor(value, 0.1)).toEqual(results[index])
})
})
})
Expand Down Expand Up @@ -398,11 +436,11 @@ describe('Normalizer', () => {
width: 0,
height: 0
},
shadowOpacity: 1,
shadowOpacity: 0.5,
shadowRadius: 5
}
expect(normalizeStylesWeb(styles)).toEqual({
boxShadow: '0 0 5px rgba(0,0,0,1)',
boxShadow: '0 0 5px rgba(0,0,0,0.5)',
shadowColor: undefined,
shadowOffset: undefined,
shadowOpacity: undefined,
Expand All @@ -420,7 +458,7 @@ describe('Normalizer', () => {
textShadowRadius: 12
}
expect(normalizeStylesWeb(styles)).toEqual({
textShadow: '-5px 0 12px rgba(255,255,255,1)',
textShadow: '-5px 0 12px #fff',
textShadowColor: undefined,
textShadowOffset: undefined,
textShadowRadius: undefined
Expand Down
3 changes: 3 additions & 0 deletions src/utils/module.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module '@react-native/normalize-colors' {
export default function normalizeColor(color: string): number | null
}
38 changes: 16 additions & 22 deletions src/utils/normalizer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// based on react-native-web normalizer
// https://github.com/necolas/react-native-web
import normalizeColors from '@react-native/normalize-colors'
import type { TextShadow, Transforms, BoxShadow } from '../types'

type Preprocessor = {
Expand All @@ -8,38 +9,31 @@ type Preprocessor = {
createTransformValue(transforms: Required<Transforms>): string,
}

// for now supports
// hex colors (3, 6, 8) chars
// colors like orange red etc.
export const normalizeColor = (color: string, opacity: number = 1) => {
if (!color.startsWith('#')) {
// If the opacity is 1 there's no need to normalize the color
if (opacity === 1) {
return color
}

if (color.length === 9) {
const [r, g, b, a] = color
.slice(1)
const integer = normalizeColors(color) as number | null

// If the colour is an unknown format, the return value is null
if (integer === null) {
return color
}

const hex = integer.toString(16).padStart(8, '0')

if (hex.length === 8) {
const [r = 0, g = 0, b = 0, a = 1] = hex
.split(/(?=(?:..)*$)/)
.map(x => parseInt(x, 16))
.filter(num => !isNaN(num))

return `rgba(${r},${g},${b},${(a as number) / 255})`
return `rgba(${r},${g},${b},${((a as number) / 255) * opacity})`
}

const sanitizedHex = color.length === 4
? color
.slice(1)
.split('')
.map(char => `${char}${char}`)
.join('')
: color.slice(1)

return sanitizedHex
.split(/(?=(?:..)*$)/)
.map(x => parseInt(x, 16))
.filter(num => !isNaN(num))
.reduce((acc, color) => `${acc}${color},`, 'rgba(')
.concat(`${opacity})`)
return color
}

export const normalizeNumericValue = (value: number) => value ? `${value}px` : value
Expand Down
4 changes: 3 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3917,7 +3917,7 @@ __metadata:
languageName: node
linkType: hard

"@react-native/normalize-colors@npm:*":
"@react-native/normalize-colors@npm:*, @react-native/normalize-colors@npm:0.74.1":
version: 0.74.1
resolution: "@react-native/normalize-colors@npm:0.74.1"
checksum: a8625a2ed4f2595c9e1a0b0877ca8ab02dab243ced6bf98c82c328c2c125ca31dd3afd1f2940f2c114af2c309b28ad24da98aa9519a761a2df796c6968c055ec
Expand Down Expand Up @@ -18017,6 +18017,7 @@ __metadata:
dependencies:
"@commitlint/config-conventional": 17.8.0
"@react-native/eslint-config": 0.74.0
"@react-native/normalize-colors": 0.74.1
"@release-it/conventional-changelog": 5.1.1
"@testing-library/react-hooks": 8.0.1
"@types/jest": 29.5.5
Expand Down Expand Up @@ -18050,6 +18051,7 @@ __metadata:
release-it: 16.2.1
typescript: 5.2.2
peerDependencies:
"@react-native/normalize-colors": "*"
react: "*"
react-native: "*"
react-native-web: "*"
Expand Down

0 comments on commit 92c3f5d

Please sign in to comment.