166 lines
5.8 KiB
JavaScript
166 lines
5.8 KiB
JavaScript
import responsivePropType from "../responsivePropType/index.mjs";
|
|
import { iterateBreakpoints } from "../breakpoints/index.mjs";
|
|
import { getPath } from "../style/index.mjs";
|
|
|
|
/* eslint-disable guard-for-in */
|
|
|
|
const EMPTY_THEME = {
|
|
internal_cache: {}
|
|
};
|
|
const properties = {
|
|
m: 'margin',
|
|
p: 'padding'
|
|
};
|
|
const directions = {
|
|
t: 'Top',
|
|
r: 'Right',
|
|
b: 'Bottom',
|
|
l: 'Left',
|
|
x: ['Left', 'Right'],
|
|
y: ['Top', 'Bottom']
|
|
};
|
|
const aliases = {
|
|
marginX: 'mx',
|
|
marginY: 'my',
|
|
paddingX: 'px',
|
|
paddingY: 'py'
|
|
};
|
|
const CSS_PROPERTIES = {};
|
|
for (const key in properties) {
|
|
CSS_PROPERTIES[key] = [properties[key]];
|
|
}
|
|
for (const keyProperty in properties) {
|
|
for (const keyDirection in directions) {
|
|
const property = properties[keyProperty];
|
|
const direction = directions[keyDirection];
|
|
const value = Array.isArray(direction) ? direction.map(dir => property + dir) : [property + direction];
|
|
CSS_PROPERTIES[keyProperty + keyDirection] = value;
|
|
}
|
|
}
|
|
for (const key in aliases) {
|
|
CSS_PROPERTIES[key] = CSS_PROPERTIES[aliases[key]];
|
|
}
|
|
|
|
/** @internal */
|
|
export const marginKeys = new Set(['m', 'mt', 'mr', 'mb', 'ml', 'mx', 'my', 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'marginX', 'marginY', 'marginInline', 'marginInlineStart', 'marginInlineEnd', 'marginBlock', 'marginBlockStart', 'marginBlockEnd']);
|
|
|
|
/** @internal */
|
|
export const paddingKeys = new Set(['p', 'pt', 'pr', 'pb', 'pl', 'px', 'py', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingX', 'paddingY', 'paddingInline', 'paddingInlineStart', 'paddingInlineEnd', 'paddingBlock', 'paddingBlockStart', 'paddingBlockEnd']);
|
|
const spacingKeys = new Set([...marginKeys, ...paddingKeys]);
|
|
export function createUnaryUnit(theme, themeKey, defaultValue, propName) {
|
|
const themeSpacing = getPath(theme, themeKey, true) ?? defaultValue;
|
|
if (typeof themeSpacing === 'number' || typeof themeSpacing === 'string') {
|
|
return val => {
|
|
if (typeof val === 'string') {
|
|
return val;
|
|
}
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
if (typeof val !== 'number') {
|
|
console.error(`MUI: Expected ${propName} argument to be a number or a string, got ${val}.`);
|
|
}
|
|
}
|
|
if (typeof themeSpacing === 'string') {
|
|
if (themeSpacing.startsWith('var(') && val === 0) {
|
|
return 0;
|
|
}
|
|
if (themeSpacing.startsWith('var(') && val === 1) {
|
|
return themeSpacing;
|
|
}
|
|
return `calc(${val} * ${themeSpacing})`;
|
|
}
|
|
return themeSpacing * val;
|
|
};
|
|
}
|
|
if (Array.isArray(themeSpacing)) {
|
|
return val => {
|
|
if (typeof val === 'string') {
|
|
return val;
|
|
}
|
|
const abs = Math.abs(val);
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
if (!Number.isInteger(abs)) {
|
|
console.error([`MUI: The \`theme.${themeKey}\` array type cannot be combined with non integer values.` + `You should either use an integer value that can be used as index, or define the \`theme.${themeKey}\` as a number.`].join('\n'));
|
|
} else if (abs > themeSpacing.length - 1) {
|
|
console.error([`MUI: The value provided (${abs}) overflows.`, `The supported values are: ${JSON.stringify(themeSpacing)}.`, `${abs} > ${themeSpacing.length - 1}, you need to add the missing values.`].join('\n'));
|
|
}
|
|
}
|
|
const transformed = themeSpacing[abs];
|
|
if (val >= 0) {
|
|
return transformed;
|
|
}
|
|
if (typeof transformed === 'number') {
|
|
return -transformed;
|
|
}
|
|
if (typeof transformed === 'string' && transformed.startsWith('var(')) {
|
|
return `calc(-1 * ${transformed})`;
|
|
}
|
|
return `-${transformed}`;
|
|
};
|
|
}
|
|
if (typeof themeSpacing === 'function') {
|
|
return themeSpacing;
|
|
}
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
console.error([`MUI: The \`theme.${themeKey}\` value (${themeSpacing}) is invalid.`, 'It should be a number, an array or a function.'].join('\n'));
|
|
}
|
|
return () => undefined;
|
|
}
|
|
export function createUnarySpacing(theme) {
|
|
return createUnaryUnit(theme, 'spacing', 8, 'spacing');
|
|
}
|
|
export function getValue(transformer, propValue) {
|
|
if (typeof propValue === 'string' || propValue == null) {
|
|
return propValue;
|
|
}
|
|
return transformer(propValue);
|
|
}
|
|
|
|
// Avoid allocations
|
|
const container = [''];
|
|
function style(props, keys) {
|
|
const theme = props.theme ?? EMPTY_THEME;
|
|
const transformer = theme?.internal_cache?.unarySpacing ?? createUnarySpacing(theme);
|
|
const result = {};
|
|
for (const prop in props) {
|
|
if (!keys.has(prop)) {
|
|
continue;
|
|
}
|
|
const cssProperties = CSS_PROPERTIES[prop] ?? (container[0] = prop, container);
|
|
const propValue = props[prop];
|
|
iterateBreakpoints(result, props.theme, propValue, (mediaKey, value) => {
|
|
const target = mediaKey ? result[mediaKey] : result;
|
|
for (let i = 0; i < cssProperties.length; i += 1) {
|
|
target[cssProperties[i]] = getValue(transformer, value);
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
function marginFn(props) {
|
|
return style(props, marginKeys);
|
|
}
|
|
marginFn.propTypes = process.env.NODE_ENV !== 'production' ? Array.from(marginKeys).reduce((obj, key) => {
|
|
obj[key] = responsivePropType;
|
|
return obj;
|
|
}, {}) : {};
|
|
marginFn.filterProps = marginKeys;
|
|
export const margin = marginFn;
|
|
function paddingFn(props) {
|
|
return style(props, paddingKeys);
|
|
}
|
|
paddingFn.propTypes = process.env.NODE_ENV !== 'production' ? Array.from(paddingKeys).reduce((obj, key) => {
|
|
obj[key] = responsivePropType;
|
|
return obj;
|
|
}, {}) : {};
|
|
paddingFn.filterProps = paddingKeys;
|
|
export const padding = paddingFn;
|
|
function spacingFn(props) {
|
|
return style(props, spacingKeys);
|
|
}
|
|
spacingFn.propTypes = process.env.NODE_ENV !== 'production' ? Array.from(spacingKeys).reduce((obj, key) => {
|
|
obj[key] = responsivePropType;
|
|
return obj;
|
|
}, {}) : {};
|
|
spacingFn.filterProps = spacingKeys;
|
|
const spacing = spacingFn;
|
|
export default spacing; |