Skip to content

Commit

Permalink
add transformer (#683)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasoppermann authored Jul 12, 2023
1 parent 4ff69fa commit a274930
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/PrimerStyleDictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
typographyToCss,
colorToHexMix,
dimensionToRem,
colorToRgbaFloat,
} from './transformers'
import {
scssMixinCssVariables,
Expand Down Expand Up @@ -104,6 +105,11 @@ StyleDictionary.registerTransform({
...colorToRgbAlpha,
})

StyleDictionary.registerTransform({
name: 'color/rgbaFloat',
...colorToRgbaFloat,
})

StyleDictionary.registerTransform({
name: 'color/hexAlpha',
...colorToHexAlpha,
Expand Down
120 changes: 120 additions & 0 deletions src/transformers/colorToRgbaFloat.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import {getMockToken} from '~/src/test-utilities'
import {colorToRgbaFloat} from './colorToRgbaFloat'

describe('Transformer: colorToRgbaFloat', () => {
it('transforms `hex3`, `hex6`, and `hex8` tokens to rgb float value', () => {
const input = [getMockToken({value: '#123'}), getMockToken({value: '#343434'}), getMockToken({value: '#34343466'})]
const expectedOutput = [
{
r: 0.06666666666666667,
g: 0.13333333333333333,
b: 0.2,
a: 1,
},
{
r: 0.20392156862745098,
g: 0.20392156862745098,
b: 0.20392156862745098,
a: 1,
},
{
r: 0.20392156862745098,
g: 0.20392156862745098,
b: 0.20392156862745098,
a: 0.4,
},
]
expect(input.map(item => colorToRgbaFloat.transformer(item, {}))).toStrictEqual(expectedOutput)
})

it('transforms `rgb` and `rgba` to rgb float value', () => {
const input = [getMockToken({value: 'rgb(100,200,255)'}), getMockToken({value: 'rgba(100,200,255, .4)'})]
const expectedOutput = [
{
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 1,
},
{
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 0.4,
},
]
expect(input.map(item => colorToRgbaFloat.transformer(item, {}))).toStrictEqual(expectedOutput)
})

it('transforms `color` tokens including alpha value', () => {
expect(
[
getMockToken({value: '#343434', alpha: 0.4}),
getMockToken({value: '#34343466', alpha: 0.9}),
getMockToken({value: 'rgb(100,200,255)', alpha: 0.4}),
getMockToken({value: 'rgba(100,200,255,0.8)', alpha: 0.4}),
].map(item => colorToRgbaFloat.transformer(item, {})),
).toStrictEqual([
{
r: 0.20392156862745098,
g: 0.20392156862745098,
b: 0.20392156862745098,
a: 0.4,
},
{
r: 0.20392156862745098,
g: 0.20392156862745098,
b: 0.20392156862745098,
a: 0.9,
},
{
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 0.4,
},
{
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 0.4,
},
])
})

it('it forwards `rgb float` values', () => {
const input = [
getMockToken({
value: {
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 1,
},
}),
getMockToken({
value: {
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 0.4,
},
}),
]
const expectedOutput = [
{
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 1,
},
{
r: 0.39215686274509803,
g: 0.7843137254901961,
b: 1,
a: 0.4,
},
]
expect(input.map(item => colorToRgbaFloat.transformer(item, {}))).toStrictEqual(expectedOutput)
})
})
52 changes: 52 additions & 0 deletions src/transformers/colorToRgbaFloat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {toHex} from 'color2k'
import {isColor} from '~/src/filters'
import type StyleDictionary from 'style-dictionary'
import {getTokenValue} from './utilities/getTokenValue'

const toRgbaFloat = (color: string, alpha?: number) => {
// get hex value from color string
const hex = toHex(color)
// retrieve spots from hex value (hex 3, hex 6 or hex 8)
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex) ?? ['00', '00', '00']
// return parsed rgba float object using alpha value from token, from hex code or defaults to 1
return {
r: parseInt(result[1], 16) / 255,
g: parseInt(result[2], 16) / 255,
b: parseInt(result[3], 16) / 255,
a: alpha !== undefined ? alpha : parseInt(result[4], 16) / 255 || 1,
}
}
// sum up the values of all values in an array
const sum = (array: unknown[]): number => array.reduce((acc: number, v: unknown) => acc + parseInt(`${v}`), 0)

const isRgbaFloat = (value: unknown) => {
if (
value &&
typeof value === `object` &&
'r' in value &&
'g' in value &&
'b' in value &&
sum(Object.values(value)) < 5
) {
return true
}
return false
}

/**
* @description converts color tokens rgba float with values from 0 - 1
* @type value transformer — [StyleDictionary.ValueTransform](https://github.com/amzn/style-dictionary/blob/main/types/Transform.d.ts)
* @matcher matches all tokens of $type `color`
* @transformer returns a `rgb` float object
*/
export const colorToRgbaFloat: StyleDictionary.Transform = {
type: `value`,
transitive: true,
matcher: isColor,
transformer: (token: StyleDictionary.TransformedToken) => {
// skip if value is already rgb float
if (isRgbaFloat(token.value)) return token.value
// convert hex or rgb values to rgba float
return toRgbaFloat(getTokenValue(token), token.alpha)
},
}
1 change: 1 addition & 0 deletions src/transformers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export {colorToHex} from './colorToHex'
export {colorToHexAlpha} from './colorToHexAlpha'
export {colorToHexMix} from './colorToHexMix'
export {colorToRgbAlpha} from './colorToRgbAlpha'
export {colorToRgbaFloat} from './colorToRgbaFloat'
export {dimensionToRem} from './dimensionToRem'
export {fontFamilyToCss} from './fontFamilyToCss'
export {fontWeightToNumber} from './fontWeightToNumber'
Expand Down

0 comments on commit a274930

Please sign in to comment.