153 lines
5.2 KiB
Plaintext
153 lines
5.2 KiB
Plaintext
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
||
|
import PropTypes from 'prop-types';
|
||
|
import deepmerge from '@mui/utils/deepmerge';
|
||
|
import merge from './merge';
|
||
|
|
||
|
// The breakpoint **start** at this value.
|
||
|
// For instance with the first breakpoint xs: [xs, sm[.
|
||
|
export const values = {
|
||
|
xs: 0,
|
||
|
// phone
|
||
|
sm: 600,
|
||
|
// tablet
|
||
|
md: 900,
|
||
|
// small laptop
|
||
|
lg: 1200,
|
||
|
// desktop
|
||
|
xl: 1536 // large screen
|
||
|
};
|
||
|
const defaultBreakpoints = {
|
||
|
// Sorted ASC by size. That's important.
|
||
|
// It can't be configured as it's used statically for propTypes.
|
||
|
keys: ['xs', 'sm', 'md', 'lg', 'xl'],
|
||
|
up: key => `@media (min-width:${values[key]}px)`
|
||
|
};
|
||
|
export function handleBreakpoints(props, propValue, styleFromPropValue) {
|
||
|
const theme = props.theme || {};
|
||
|
if (Array.isArray(propValue)) {
|
||
|
const themeBreakpoints = theme.breakpoints || defaultBreakpoints;
|
||
|
return propValue.reduce((acc, item, index) => {
|
||
|
acc[themeBreakpoints.up(themeBreakpoints.keys[index])] = styleFromPropValue(propValue[index]);
|
||
|
return acc;
|
||
|
}, {});
|
||
|
}
|
||
|
if (typeof propValue === 'object') {
|
||
|
const themeBreakpoints = theme.breakpoints || defaultBreakpoints;
|
||
|
return Object.keys(propValue).reduce((acc, breakpoint) => {
|
||
|
// key is breakpoint
|
||
|
if (Object.keys(themeBreakpoints.values || values).indexOf(breakpoint) !== -1) {
|
||
|
const mediaKey = themeBreakpoints.up(breakpoint);
|
||
|
acc[mediaKey] = styleFromPropValue(propValue[breakpoint], breakpoint);
|
||
|
} else {
|
||
|
const cssKey = breakpoint;
|
||
|
acc[cssKey] = propValue[cssKey];
|
||
|
}
|
||
|
return acc;
|
||
|
}, {});
|
||
|
}
|
||
|
const output = styleFromPropValue(propValue);
|
||
|
return output;
|
||
|
}
|
||
|
function breakpoints(styleFunction) {
|
||
|
// false positive
|
||
|
// eslint-disable-next-line react/function-component-definition
|
||
|
const newStyleFunction = props => {
|
||
|
const theme = props.theme || {};
|
||
|
const base = styleFunction(props);
|
||
|
const themeBreakpoints = theme.breakpoints || defaultBreakpoints;
|
||
|
const extended = themeBreakpoints.keys.reduce((acc, key) => {
|
||
|
if (props[key]) {
|
||
|
acc = acc || {};
|
||
|
acc[themeBreakpoints.up(key)] = styleFunction(_extends({
|
||
|
theme
|
||
|
}, props[key]));
|
||
|
}
|
||
|
return acc;
|
||
|
}, null);
|
||
|
return merge(base, extended);
|
||
|
};
|
||
|
newStyleFunction.propTypes = process.env.NODE_ENV !== 'production' ? _extends({}, styleFunction.propTypes, {
|
||
|
xs: PropTypes.object,
|
||
|
sm: PropTypes.object,
|
||
|
md: PropTypes.object,
|
||
|
lg: PropTypes.object,
|
||
|
xl: PropTypes.object
|
||
|
}) : {};
|
||
|
newStyleFunction.filterProps = ['xs', 'sm', 'md', 'lg', 'xl', ...styleFunction.filterProps];
|
||
|
return newStyleFunction;
|
||
|
}
|
||
|
export function createEmptyBreakpointObject(breakpointsInput = {}) {
|
||
|
var _breakpointsInput$key;
|
||
|
const breakpointsInOrder = (_breakpointsInput$key = breakpointsInput.keys) == null ? void 0 : _breakpointsInput$key.reduce((acc, key) => {
|
||
|
const breakpointStyleKey = breakpointsInput.up(key);
|
||
|
acc[breakpointStyleKey] = {};
|
||
|
return acc;
|
||
|
}, {});
|
||
|
return breakpointsInOrder || {};
|
||
|
}
|
||
|
export function removeUnusedBreakpoints(breakpointKeys, style) {
|
||
|
return breakpointKeys.reduce((acc, key) => {
|
||
|
const breakpointOutput = acc[key];
|
||
|
const isBreakpointUnused = !breakpointOutput || Object.keys(breakpointOutput).length === 0;
|
||
|
if (isBreakpointUnused) {
|
||
|
delete acc[key];
|
||
|
}
|
||
|
return acc;
|
||
|
}, style);
|
||
|
}
|
||
|
export function mergeBreakpointsInOrder(breakpointsInput, ...styles) {
|
||
|
const emptyBreakpoints = createEmptyBreakpointObject(breakpointsInput);
|
||
|
const mergedOutput = [emptyBreakpoints, ...styles].reduce((prev, next) => deepmerge(prev, next), {});
|
||
|
return removeUnusedBreakpoints(Object.keys(emptyBreakpoints), mergedOutput);
|
||
|
}
|
||
|
|
||
|
// compute base for responsive values; e.g.,
|
||
|
// [1,2,3] => {xs: true, sm: true, md: true}
|
||
|
// {xs: 1, sm: 2, md: 3} => {xs: true, sm: true, md: true}
|
||
|
export function computeBreakpointsBase(breakpointValues, themeBreakpoints) {
|
||
|
// fixed value
|
||
|
if (typeof breakpointValues !== 'object') {
|
||
|
return {};
|
||
|
}
|
||
|
const base = {};
|
||
|
const breakpointsKeys = Object.keys(themeBreakpoints);
|
||
|
if (Array.isArray(breakpointValues)) {
|
||
|
breakpointsKeys.forEach((breakpoint, i) => {
|
||
|
if (i < breakpointValues.length) {
|
||
|
base[breakpoint] = true;
|
||
|
}
|
||
|
});
|
||
|
} else {
|
||
|
breakpointsKeys.forEach(breakpoint => {
|
||
|
if (breakpointValues[breakpoint] != null) {
|
||
|
base[breakpoint] = true;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
return base;
|
||
|
}
|
||
|
export function resolveBreakpointValues({
|
||
|
values: breakpointValues,
|
||
|
breakpoints: themeBreakpoints,
|
||
|
base: customBase
|
||
|
}) {
|
||
|
const base = customBase || computeBreakpointsBase(breakpointValues, themeBreakpoints);
|
||
|
const keys = Object.keys(base);
|
||
|
if (keys.length === 0) {
|
||
|
return breakpointValues;
|
||
|
}
|
||
|
let previous;
|
||
|
return keys.reduce((acc, breakpoint, i) => {
|
||
|
if (Array.isArray(breakpointValues)) {
|
||
|
acc[breakpoint] = breakpointValues[i] != null ? breakpointValues[i] : breakpointValues[previous];
|
||
|
previous = i;
|
||
|
} else if (typeof breakpointValues === 'object') {
|
||
|
acc[breakpoint] = breakpointValues[breakpoint] != null ? breakpointValues[breakpoint] : breakpointValues[previous];
|
||
|
previous = breakpoint;
|
||
|
} else {
|
||
|
acc[breakpoint] = breakpointValues;
|
||
|
}
|
||
|
return acc;
|
||
|
}, {});
|
||
|
}
|
||
|
export default breakpoints;
|