UNPKG

@re-flex/styles

Version:
134 lines (133 loc) 5.49 kB
import { convertUnit2Rem, hasKey, isArray, isObject } from "@re-flex/utils"; import { UI_ACTIVE_THEME } from "./Core"; import parseColor from "./parseColor"; const multiples = { size: ["width", "height"], }; const transformList = { bgColor: "backgroundColor", w: "width", h: "height", m: "margin", mt: "marginTop", mr: "marginRight", mb: "marginBottom", ml: "marginLeft", marginX: "marginInline", marginY: "marginBlock", mx: "marginInline", my: "marginBlock", p: "padding", pt: "paddingTop", pr: "paddingRight", pb: "paddingBottom", pl: "paddingLeft", paddingX: "paddingInline", paddingY: "paddingBlock", px: "paddingInline", py: "paddingBlock", }; const ColorList = new Set([ Object.keys(UI_ACTIVE_THEME.palette.background), Object.keys(UI_ACTIVE_THEME.palette), ].flat()); const setTransformList = new Set(Object.keys(transformList)); const SpacePropList = new Set("paddingBlock|paddingInline|marginBlock|marginInline|m|mx|my|mt|ml|mr|mb|p|px|py|pt|pl|pr|pb|margin|marginTop|marginRight|marginBottom|marginLeft|marginX|marginY|padding|paddingTop|paddingRight|paddingBottom|paddingLeft|paddingX|paddingY|top|right|bottom|left|gridGap|gridColumnGap|gridRowGap|gap|columnGap|rowGap|borderRadius".split("|")); const ColorPropList = new Set("bgColor|color|backgroundColor|borderColor|borderTopColor|borderBottomColor|borderLeftColor|borderRightColor|outlineColor|fill|stroke".split("|")); const SizePropList = new Set("fontSize|letterSpacing|width|minWidth|maxWidth|height|minHeight|maxHeight|flexBasis|size".split("|")); const UnitLessPropList = new Set("inset|fontWeight|animationDuration|animationDelay|transitionDuration|transitionDelay|animationIterationCount|borderImageOutset|borderImageSlice|borderImageWidth|boxFlex|boxFlexGroup|boxOrdinalGroup|columnCount|columns|flex|flexGrow|flexPositive|flexShrink|flexNegative|flexOrder|gridRow|gridRowEnd|gridRowSpan|gridRowStart|gridColumn|gridColumnEnd|gridColumnSpan|gridColumnStart|msGridRow|msGridRowSpan|msGridColumn|msGridColumnSpan|fontWeight|lineHeight|opacity|order|orphans|tabSize|widows|zIndex|zoom|WebkitLineClamp|fillOpacity|floodOpacity|stopOpacity|strokeDasharray|strokeDashoffset|strokeMiterlimit|strokeOpacity|strokeWidth".split("|")); const COLOR_CACHE = {}; const hasColor = (prop, value) => { const key = prop + value; if (hasKey(COLOR_CACHE, key)) return COLOR_CACHE[key]; if (ColorPropList.has(prop)) { if (value.startsWith("var(")) { COLOR_CACHE[key] = false; return false; } let isCustomColor = value.includes(".") || ColorList.has(value); COLOR_CACHE[key] = isCustomColor; return isCustomColor; } COLOR_CACHE[key] = false; return false; }; const sxValueTransformerCache = {}; const sxValueTransformer = (prop, value) => { let result = {}; if (setTransformList.has(prop)) { prop = transformList[prop]; } if (hasColor(prop, value)) { let { primaryColor } = parseColor(value); value = primaryColor; } else if (SpacePropList.has(prop) && typeof value === "number") { value = convertUnit2Rem(value * UI_ACTIVE_THEME.space); } else if (SizePropList.has(prop) && typeof value === "number") { value = convertUnit2Rem(value); } else if (prop === "boxShadow" && typeof value === "number") { value = UI_ACTIVE_THEME.shadows?.[value] || "none"; } else if (UnitLessPropList.has(prop) && typeof value === "number") { value = String(value); } if (isArray(multiples[prop])) { let dirs = multiples[prop]; for (let i = 0; i < dirs.length; i++) { result[dirs[i]] = value; } } else { result[prop] = value; } return result; }; const sxParser = (styles) => { let result = {}; for (const prop in styles) { let value = styles[prop]; if (!value) return {}; if (isObject(value)) { if (Object.keys(value).length === 0) return {}; if (UI_ACTIVE_THEME.breakpoints.has(prop)) { result[UI_ACTIVE_THEME.breakpoints.up(prop)] = sxParser(value); } else { if ([".", "#", "[", "@", "-"].includes(prop[0]) === false && Object.keys(value).some((val) => UI_ACTIVE_THEME.breakpoints.has(val))) { for (const breakPoint in value) { let val = value; result[UI_ACTIVE_THEME.breakpoints.up(breakPoint)] = Object.assign({}, result[UI_ACTIVE_THEME.breakpoints.up(breakPoint)], sxValueTransformer(prop, val)); } } else { result[prop] = sxParser(value); } } } else { let transformedProperties = sxValueTransformer(prop, value); for (const key in transformedProperties) { result[key] = transformedProperties[key]; } } } return result; }; export const sxPropInitializer = (args) => { const theme = UI_ACTIVE_THEME; const sxStyles = typeof args === "function" ? args(theme) : args; if (!sxStyles || Object.keys(sxStyles).length === 0) { return {}; } const sStyles = sxParser(sxStyles); return sStyles; }; export default sxPropInitializer;