@hakuna-matata-ui/styled-system
Version:
Style function for css-in-js building component libraries
98 lines (83 loc) • 2.29 kB
text/typescript
import { Dict, walkObject } from "@hakuna-matata-ui/utils"
import { ThemeScale } from "./theme-tokens"
import { calc, Operand } from "./calc"
import { cssVar } from "./css-var"
export interface CreateThemeVarsOptions {
cssVarPrefix?: string
}
export interface ThemeVars {
cssVars: Dict
cssMap: Dict
}
export function createThemeVars(target: Dict, options: CreateThemeVarsOptions) {
const context: ThemeVars = {
cssMap: {},
cssVars: {},
}
walkObject(target, (value, path) => {
// firstKey will be e.g. "space"
const [firstKey] = path
const handler = tokenHandlerMap[firstKey] ?? tokenHandlerMap.defaultHandler
const { cssVars, cssMap } = handler(path, value, options)
Object.assign(context.cssVars, cssVars)
Object.assign(context.cssMap, cssMap)
})
return context
}
type TokenHandler = (
keys: string[],
value: unknown | { reference: string },
options: CreateThemeVarsOptions,
) => ThemeVars
/**
* Define transformation handlers for ThemeScale
*/
const tokenHandlerMap: Partial<Record<ThemeScale, TokenHandler>> & {
defaultHandler: TokenHandler
} = {
space: (keys, value, options) => {
const properties = tokenHandlerMap.defaultHandler(keys, value, options)
const [firstKey, ...referenceKeys] = keys
const negativeLookupKey = `${firstKey}.-${referenceKeys.join(".")}`
const negativeVarKey = keys.join("-")
const { variable, reference } = cssVar(
negativeVarKey,
undefined,
options.cssVarPrefix,
)
const negativeValue = calc.negate(value as Operand)
const varRef = calc.negate(reference)
return {
cssVars: properties.cssVars,
cssMap: {
...properties.cssMap,
[negativeLookupKey]: {
value: `${negativeValue}`,
var: `${variable}`,
varRef,
},
},
}
},
defaultHandler: (keys, value, options) => {
const lookupKey = keys.join(".")
const varKey = keys.join("-")
const { variable, reference } = cssVar(
varKey,
undefined,
options.cssVarPrefix,
)
return {
cssVars: {
[variable]: value,
},
cssMap: {
[lookupKey]: {
value,
var: variable,
varRef: reference,
},
},
}
},
}