@hakuna-matata-ui/styled-system
Version:
Style function for css-in-js building component libraries
61 lines (47 loc) • 1.61 kB
text/typescript
import { Dict, isObject, runIfFn } from "@hakuna-matata-ui/utils"
/**
* Expands an array or object syntax responsive style.
*
* @example
* expandResponsive({ mx: [1, 2] })
* // or
* expandResponsive({ mx: { base: 1, sm: 2 } })
*
* // => { mx: 1, "@media(min-width:<sm>)": { mx: 2 } }
*/
export const expandResponsive = (styles: Dict) => (theme: Dict) => {
/**
* Before any style can be processed, the user needs to call `toCSSVar`
* which analyzes the theme's breakpoint and appends a `__breakpoints` property
* to the theme with more details of the breakpoints.
*
* To learn more, go here: packages/utils/src/responsive.ts #analyzeBreakpoints
*/
if (!theme.__breakpoints) return styles
const { isResponsive, toArrayValue, media: medias } = theme.__breakpoints
const computedStyles: Dict = {}
for (const key in styles) {
let value = runIfFn(styles[key], theme)
if (value == null) continue
// converts the object responsive syntax to array syntax
value = isObject(value) && isResponsive(value) ? toArrayValue(value) : value
if (!Array.isArray(value)) {
computedStyles[key] = value
continue
}
const queries = value.slice(0, medias.length).length
for (let index = 0; index < queries; index += 1) {
const media = medias?.[index]
if (!media) {
computedStyles[key] = value[index]
continue
}
computedStyles[media] = computedStyles[media] || {}
if (value[index] == null) {
continue
}
computedStyles[media][key] = value[index]
}
}
return computedStyles
}