UNPKG

@mui/system

Version:

MUI System is a set of CSS utilities to help you build custom designs more efficiently. It makes it possible to rapidly lay out custom designs.

127 lines (124 loc) 4.24 kB
import capitalize from '@mui/utils/capitalize'; import merge from "../merge/index.js"; import { getPath, getStyleValue as getValue } from "../style/index.js"; import { handleBreakpoints, createEmptyBreakpointObject, removeUnusedBreakpoints } from "../breakpoints/index.js"; import { sortContainerQueries } from "../cssContainerQueries/index.js"; import defaultSxConfig from "./defaultSxConfig.js"; function objectsHaveSameKeys(...objects) { const allKeys = objects.reduce((keys, object) => keys.concat(Object.keys(object)), []); const union = new Set(allKeys); return objects.every(object => union.size === Object.keys(object).length); } function callIfFn(maybeFn, arg) { return typeof maybeFn === 'function' ? maybeFn(arg) : maybeFn; } // eslint-disable-next-line @typescript-eslint/naming-convention export function unstable_createStyleFunctionSx() { function getThemeValue(prop, val, theme, config) { const props = { [prop]: val, theme }; const options = config[prop]; if (!options) { return { [prop]: val }; } const { cssProperty = prop, themeKey, transform, style } = options; if (val == null) { return null; } // TODO v6: remove, see https://github.com/mui/material-ui/pull/38123 if (themeKey === 'typography' && val === 'inherit') { return { [prop]: val }; } const themeMapping = getPath(theme, themeKey) || {}; if (style) { return style(props); } const styleFromPropValue = propValueFinal => { let value = getValue(themeMapping, transform, propValueFinal); if (propValueFinal === value && typeof propValueFinal === 'string') { // Haven't found value value = getValue(themeMapping, transform, `${prop}${propValueFinal === 'default' ? '' : capitalize(propValueFinal)}`, propValueFinal); } if (cssProperty === false) { return value; } return { [cssProperty]: value }; }; return handleBreakpoints(props, val, styleFromPropValue); } function styleFunctionSx(props) { const { sx, theme = {} } = props || {}; if (!sx) { return null; // Emotion & styled-components will neglect null } const config = theme.unstable_sxConfig ?? defaultSxConfig; /* * Receive `sxInput` as object or callback * and then recursively check keys & values to create media query object styles. * (the result will be used in `styled`) */ function traverse(sxInput) { let sxObject = sxInput; if (typeof sxInput === 'function') { sxObject = sxInput(theme); } else if (typeof sxInput !== 'object') { // value return sxInput; } if (!sxObject) { return null; } const emptyBreakpoints = createEmptyBreakpointObject(theme.breakpoints); const breakpointsKeys = Object.keys(emptyBreakpoints); let css = emptyBreakpoints; Object.keys(sxObject).forEach(styleKey => { const value = callIfFn(sxObject[styleKey], theme); if (value !== null && value !== undefined) { if (typeof value === 'object') { if (config[styleKey]) { css = merge(css, getThemeValue(styleKey, value, theme, config)); } else { const breakpointsValues = handleBreakpoints({ theme }, value, x => ({ [styleKey]: x })); if (objectsHaveSameKeys(breakpointsValues, value)) { css[styleKey] = styleFunctionSx({ sx: value, theme }); } else { css = merge(css, breakpointsValues); } } } else { css = merge(css, getThemeValue(styleKey, value, theme, config)); } } }); return sortContainerQueries(theme, removeUnusedBreakpoints(breakpointsKeys, css)); } return Array.isArray(sx) ? sx.map(traverse) : traverse(sx); } return styleFunctionSx; } const styleFunctionSx = unstable_createStyleFunctionSx(); styleFunctionSx.filterProps = ['sx']; export default styleFunctionSx;