@material-ui/core
Version:
React components that implement Google's Material Design.
234 lines (212 loc) • 8.02 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import { formatMuiErrorMessage as _formatMuiErrorMessage } from "@material-ui/utils";
import { deepmerge } from '@material-ui/utils';
import common from '../colors/common';
import grey from '../colors/grey';
import indigo from '../colors/indigo';
import pink from '../colors/pink';
import red from '../colors/red';
import orange from '../colors/orange';
import blue from '../colors/blue';
import green from '../colors/green';
import { darken, getContrastRatio, lighten } from './colorManipulator';
export const light = {
// The colors used to style the text.
text: {
// The most important text.
primary: 'rgba(0, 0, 0, 0.87)',
// Secondary text.
secondary: 'rgba(0, 0, 0, 0.54)',
// Disabled text have even lower visual prominence.
disabled: 'rgba(0, 0, 0, 0.38)',
// Text hints.
hint: 'rgba(0, 0, 0, 0.38)'
},
// The color used to divide different elements.
divider: 'rgba(0, 0, 0, 0.12)',
// The background colors used to style the surfaces.
// Consistency between these values is important.
background: {
paper: common.white,
default: grey[50]
},
// The colors used to style the action elements.
action: {
// The color of an active action like an icon button.
active: 'rgba(0, 0, 0, 0.54)',
// The color of an hovered action.
hover: 'rgba(0, 0, 0, 0.04)',
hoverOpacity: 0.04,
// The color of a selected action.
selected: 'rgba(0, 0, 0, 0.08)',
selectedOpacity: 0.08,
// The color of a disabled action.
disabled: 'rgba(0, 0, 0, 0.26)',
// The background color of a disabled action.
disabledBackground: 'rgba(0, 0, 0, 0.12)',
disabledOpacity: 0.38,
focus: 'rgba(0, 0, 0, 0.12)',
focusOpacity: 0.12,
activatedOpacity: 0.12
}
};
export const dark = {
text: {
primary: common.white,
secondary: 'rgba(255, 255, 255, 0.7)',
disabled: 'rgba(255, 255, 255, 0.5)',
hint: 'rgba(255, 255, 255, 0.5)',
icon: 'rgba(255, 255, 255, 0.5)'
},
divider: 'rgba(255, 255, 255, 0.12)',
background: {
paper: grey[800],
default: '#303030'
},
action: {
active: common.white,
hover: 'rgba(255, 255, 255, 0.08)',
hoverOpacity: 0.08,
selected: 'rgba(255, 255, 255, 0.16)',
selectedOpacity: 0.16,
disabled: 'rgba(255, 255, 255, 0.3)',
disabledBackground: 'rgba(255, 255, 255, 0.12)',
disabledOpacity: 0.38,
focus: 'rgba(255, 255, 255, 0.12)',
focusOpacity: 0.12,
activatedOpacity: 0.24
}
};
function addLightOrDark(intent, direction, shade, tonalOffset) {
const tonalOffsetLight = tonalOffset.light || tonalOffset;
const tonalOffsetDark = tonalOffset.dark || tonalOffset * 1.5;
if (!intent[direction]) {
if (intent.hasOwnProperty(shade)) {
intent[direction] = intent[shade];
} else if (direction === 'light') {
intent.light = lighten(intent.main, tonalOffsetLight);
} else if (direction === 'dark') {
intent.dark = darken(intent.main, tonalOffsetDark);
}
}
}
export default function createPalette(palette) {
const {
primary = {
light: indigo[300],
main: indigo[500],
dark: indigo[700]
},
secondary = {
light: pink.A200,
main: pink.A400,
dark: pink.A700
},
error = {
light: red[300],
main: red[500],
dark: red[700]
},
warning = {
light: orange[300],
main: orange[500],
dark: orange[700]
},
info = {
light: blue[300],
main: blue[500],
dark: blue[700]
},
success = {
light: green[300],
main: green[500],
dark: green[700]
},
type = 'light',
contrastThreshold = 3,
tonalOffset = 0.2
} = palette,
other = _objectWithoutPropertiesLoose(palette, ["primary", "secondary", "error", "warning", "info", "success", "type", "contrastThreshold", "tonalOffset"]); // Use the same logic as
// Bootstrap: https://github.com/twbs/bootstrap/blob/1d6e3710dd447de1a200f29e8fa521f8a0908f70/scss/_functions.scss#L59
// and material-components-web https://github.com/material-components/material-components-web/blob/ac46b8863c4dab9fc22c4c662dc6bd1b65dd652f/packages/mdc-theme/_functions.scss#L54
function getContrastText(background) {
const contrastText = getContrastRatio(background, dark.text.primary) >= contrastThreshold ? dark.text.primary : light.text.primary;
if (process.env.NODE_ENV !== 'production') {
const contrast = getContrastRatio(background, contrastText);
if (contrast < 3) {
console.error([`Material-UI: The contrast ratio of ${contrast}:1 for ${contrastText} on ${background}`, 'falls below the WCAG recommended absolute minimum contrast ratio of 3:1.', 'https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast'].join('\n'));
}
}
return contrastText;
}
const augmentColor = (color, mainShade = 500, lightShade = 300, darkShade = 700) => {
color = _extends({}, color);
if (!color.main && color[mainShade]) {
color.main = color[mainShade];
}
if (!color.main) {
throw new Error(process.env.NODE_ENV !== "production" ? `Material-UI: The color provided to augmentColor(color) is invalid.
The color object needs to have a \`main\` property or a \`${mainShade}\` property.` : _formatMuiErrorMessage(4, mainShade));
}
if (typeof color.main !== 'string') {
throw new Error(process.env.NODE_ENV !== "production" ? `Material-UI: The color provided to augmentColor(color) is invalid.
\`color.main\` should be a string, but \`${JSON.stringify(color.main)}\` was provided instead.
Did you intend to use one of the following approaches?
import { green } from "@material-ui/core/colors";
const theme1 = createTheme({ palette: {
primary: green,
} });
const theme2 = createTheme({ palette: {
primary: { main: green[500] },
} });` : _formatMuiErrorMessage(5, JSON.stringify(color.main)));
}
addLightOrDark(color, 'light', lightShade, tonalOffset);
addLightOrDark(color, 'dark', darkShade, tonalOffset);
if (!color.contrastText) {
color.contrastText = getContrastText(color.main);
}
return color;
};
const types = {
dark,
light
};
if (process.env.NODE_ENV !== 'production') {
if (!types[type]) {
console.error(`Material-UI: The palette type \`${type}\` is not supported.`);
}
}
const paletteOutput = deepmerge(_extends({
// A collection of common colors.
common,
// The palette type, can be light or dark.
type,
// The colors used to represent primary interface elements for a user.
primary: augmentColor(primary),
// The colors used to represent secondary interface elements for a user.
secondary: augmentColor(secondary, 'A400', 'A200', 'A700'),
// The colors used to represent interface elements that the user should be made aware of.
error: augmentColor(error),
// The colors used to represent potentially dangerous actions or important messages.
warning: augmentColor(warning),
// The colors used to present information to the user that is neutral and not necessarily important.
info: augmentColor(info),
// The colors used to indicate the successful completion of an action that user triggered.
success: augmentColor(success),
// The grey colors.
grey,
// Used by `getContrastText()` to maximize the contrast between
// the background and the text.
contrastThreshold,
// Takes a background color and returns the text color that maximizes the contrast.
getContrastText,
// Generate a rich color object.
augmentColor,
// Used by the functions below to shift a color's luminance by approximately
// two indexes within its tonal palette.
// E.g., shift from Red 500 to Red 300 or Red 700.
tonalOffset
}, types[type]), other);
return paletteOutput;
}