UNPKG

@hakuna-matata-ui/styled-system

Version:

Style function for css-in-js building component libraries

84 lines (65 loc) 2.25 kB
import { Dict, isString } from "@hakuna-matata-ui/utils" import { Transform } from "./types" const directionMap = { "to-t": "to top", "to-tr": "to top right", "to-r": "to right", "to-br": "to bottom right", "to-b": "to bottom", "to-bl": "to bottom left", "to-l": "to left", "to-tl": "to top left", } const valueSet = new Set(Object.values(directionMap)) export const globalSet = new Set([ "none", "-moz-initial", "inherit", "initial", "revert", "unset", ]) const trimSpace = (str: string) => str.trim() export function parseGradient(value: string | null | undefined, theme: Dict) { if (value == null || globalSet.has(value)) return value const regex = /(?<type>^[a-z-A-Z]+)\((?<values>(.*))\)/g const { type, values } = regex.exec(value)?.groups ?? {} if (!type || !values) return value const _type = type.includes("-gradient") ? type : `${type}-gradient` const [maybeDirection, ...stops] = values .split(",") .map(trimSpace) .filter(Boolean) if (stops?.length === 0) return value const direction = maybeDirection in directionMap ? directionMap[maybeDirection] : maybeDirection stops.unshift(direction) const _values = stops.map((stop) => { // if stop is valid shorthand direction, return it if (valueSet.has(stop)) return stop const firstStop = stop.indexOf(" ") // color stop could be `red.200 20%` based on css gradient spec const [_color, _stop] = firstStop !== -1 ? [stop.substr(0, firstStop), stop.substr(firstStop + 1)] : [stop] const _stopOrFunc = isCSSFunction(_stop) ? _stop : _stop && _stop.split(" ") // else, get and transform the color token or css value const key = `colors.${_color}` const color = key in theme.__cssMap ? theme.__cssMap[key].varRef : _color return _stopOrFunc ? [ color, ...(Array.isArray(_stopOrFunc) ? _stopOrFunc : [_stopOrFunc]), ].join(" ") : color }) return `${_type}(${_values.join(", ")})` } export const isCSSFunction = (value: unknown) => { return isString(value) && value.includes("(") && value.includes(")") } export const gradientTransform: Transform = (value, theme) => parseGradient(value, theme ?? {})