@sanity/ui
Version:
The Sanity UI components.
86 lines (65 loc) • 2.02 kB
text/typescript
import {ColorTint as ColorPaletteValue} from '@sanity/color'
import {parseTokenValue, ThemeColorPalette} from '../config'
import {ThemeColorBlendModeKey} from '../system'
import {hexToRgb, mix, rgba, rgbToHex} from './lib/color-fns'
import {mixThemeColor} from './mixThemeColor'
export interface RenderColorValueOptions {
bg?: string
blendMode: ThemeColorBlendModeKey
colorPalette: ThemeColorPalette
}
export function renderColorValue(str: string, options: RenderColorValueOptions): string {
const {bg, blendMode, colorPalette} = options
if (bg === 'white') {
throw new Error('Cannot blend with white background')
}
const node = parseTokenValue(str)
if (!node || node.type !== 'color') {
throw new Error(`Invalid color token value: ${str}`)
}
let hex = ''
if (node.key === 'black') {
hex = renderColorHex(colorPalette.black)
}
if (node.key === 'white') {
hex = renderColorHex(colorPalette.white)
}
if (node.hue && node.tint) {
hex = renderColorHex(colorPalette[node.hue][node.tint])
}
if (!hex) {
throw new Error(`Invalid color token value: ${str}`)
}
const hexBeforeMix = hex
const mixOptions = {
blendMode,
bg,
black: renderColorHex(colorPalette.black),
// opacity: node.opacity,
white: renderColorHex(colorPalette.white),
}
try {
hex = mixThemeColor(hex, mixOptions)
if (bg && node.mix !== undefined) {
const from = hexToRgb(bg)
const to = hexToRgb(hex)
hex = rgbToHex(mix(from, to, node.mix))
}
} catch (err) {
// eslint-disable-next-line no-console
console.warn('could not blend', hex, mixOptions)
throw err
}
if (hex === '#aN') {
// eslint-disable-next-line no-console
console.warn(`invalid color token value: ${str}`)
hex = hexBeforeMix
}
if (node.opacity !== undefined) {
hex = rgba(hex, node.opacity)
}
return hex
}
function renderColorHex(color: string | ColorPaletteValue) {
return typeof color === 'string' ? color : color.hex
}