UNPKG

@mui/joy

Version:

Joy UI is an open-source React component library that implements MUI's own design principles. It's comprehensive and can be used in production out of the box.

472 lines (467 loc) 23.1 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; const _excluded = ["cssVarPrefix", "breakpoints", "spacing", "components", "variants", "shouldSkipGeneratingVar"], _excluded2 = ["colorSchemes"]; import { deepmerge } from '@mui/utils'; import { createBreakpoints, createSpacing, colorChannel, unstable_prepareCssVars as prepareCssVars, unstable_createGetCssVar as systemCreateGetCssVar, unstable_styleFunctionSx as styleFunctionSx } from '@mui/system'; import { unstable_applyStyles as applyStyles } from '@mui/system/createTheme'; import defaultSxConfig from './sxConfig'; import colors from '../colors'; import defaultShouldSkipGeneratingVar from './shouldSkipGeneratingVar'; import { generateUtilityClass } from '../className'; import { createVariant } from './variantUtils'; // Use Partial2Level instead of PartialDeep because nested value type is CSSObject which does not work with PartialDeep. export const createGetCssVar = (cssVarPrefix = 'joy') => systemCreateGetCssVar(cssVarPrefix); export default function extendTheme(themeOptions) { var _scalesInput$colorSch, _scalesInput$colorSch2, _scalesInput$colorSch3, _scalesInput$colorSch4, _scalesInput$colorSch5, _scalesInput$colorSch6, _scalesInput$focus$th, _scalesInput$focus, _scalesInput$focus$th2, _scalesInput$focus2; const _ref = themeOptions || {}, { cssVarPrefix = 'joy', breakpoints, spacing, components: componentsInput, variants: variantsInput, shouldSkipGeneratingVar = defaultShouldSkipGeneratingVar } = _ref, scalesInput = _objectWithoutPropertiesLoose(_ref, _excluded); const getCssVar = createGetCssVar(cssVarPrefix); const defaultColors = { primary: colors.blue, neutral: colors.grey, danger: colors.red, success: colors.green, warning: colors.yellow, common: { white: '#FFF', black: '#000' } }; const getCssVarColor = cssVar => { var _defaultColors$color; const tokens = cssVar.split('-'); const color = tokens[1]; const index = tokens[2]; // @ts-ignore return getCssVar(cssVar, (_defaultColors$color = defaultColors[color]) == null ? void 0 : _defaultColors$color[index]); }; const createLightModeVariantVariables = color => ({ plainColor: getCssVarColor(`palette-${color}-500`), plainHoverBg: getCssVarColor(`palette-${color}-100`), plainActiveBg: getCssVarColor(`palette-${color}-200`), plainDisabledColor: getCssVarColor(`palette-neutral-400`), outlinedColor: getCssVarColor(`palette-${color}-500`), outlinedBorder: getCssVarColor(`palette-${color}-300`), outlinedHoverBg: getCssVarColor(`palette-${color}-100`), outlinedActiveBg: getCssVarColor(`palette-${color}-200`), outlinedDisabledColor: getCssVarColor(`palette-neutral-400`), outlinedDisabledBorder: getCssVarColor(`palette-neutral-200`), softColor: getCssVarColor(`palette-${color}-700`), softBg: getCssVarColor(`palette-${color}-100`), softHoverBg: getCssVarColor(`palette-${color}-200`), softActiveColor: getCssVarColor(`palette-${color}-800`), softActiveBg: getCssVarColor(`palette-${color}-300`), softDisabledColor: getCssVarColor(`palette-neutral-400`), softDisabledBg: getCssVarColor(`palette-neutral-50`), solidColor: getCssVarColor(`palette-common-white`), solidBg: getCssVarColor(`palette-${color}-500`), solidHoverBg: getCssVarColor(`palette-${color}-600`), solidActiveBg: getCssVarColor(`palette-${color}-700`), solidDisabledColor: getCssVarColor(`palette-neutral-400`), solidDisabledBg: getCssVarColor(`palette-neutral-100`) }); const createDarkModeVariantVariables = color => ({ plainColor: getCssVarColor(`palette-${color}-300`), plainHoverBg: getCssVarColor(`palette-${color}-800`), plainActiveBg: getCssVarColor(`palette-${color}-700`), plainDisabledColor: getCssVarColor(`palette-neutral-500`), outlinedColor: getCssVarColor(`palette-${color}-200`), outlinedBorder: getCssVarColor(`palette-${color}-700`), outlinedHoverBg: getCssVarColor(`palette-${color}-800`), outlinedActiveBg: getCssVarColor(`palette-${color}-700`), outlinedDisabledColor: getCssVarColor(`palette-neutral-500`), outlinedDisabledBorder: getCssVarColor(`palette-neutral-800`), softColor: getCssVarColor(`palette-${color}-200`), softBg: getCssVarColor(`palette-${color}-800`), softHoverBg: getCssVarColor(`palette-${color}-700`), softActiveColor: getCssVarColor(`palette-${color}-100`), softActiveBg: getCssVarColor(`palette-${color}-600`), softDisabledColor: getCssVarColor(`palette-neutral-500`), softDisabledBg: getCssVarColor(`palette-neutral-800`), solidColor: getCssVarColor(`palette-common-white`), solidBg: getCssVarColor(`palette-${color}-500`), solidHoverBg: getCssVarColor(`palette-${color}-600`), solidActiveBg: getCssVarColor(`palette-${color}-700`), solidDisabledColor: getCssVarColor(`palette-neutral-500`), solidDisabledBg: getCssVarColor(`palette-neutral-800`) }); const lightColorSystem = { palette: { mode: 'light', primary: _extends({}, defaultColors.primary, createLightModeVariantVariables('primary')), neutral: _extends({}, defaultColors.neutral, createLightModeVariantVariables('neutral'), { plainColor: getCssVarColor('palette-neutral-700'), plainHoverColor: getCssVarColor(`palette-neutral-900`), outlinedColor: getCssVarColor('palette-neutral-700') }), danger: _extends({}, defaultColors.danger, createLightModeVariantVariables('danger')), success: _extends({}, defaultColors.success, createLightModeVariantVariables('success')), warning: _extends({}, defaultColors.warning, createLightModeVariantVariables('warning')), common: { white: '#FFF', black: '#000' }, text: { primary: getCssVarColor('palette-neutral-800'), secondary: getCssVarColor('palette-neutral-700'), tertiary: getCssVarColor('palette-neutral-600'), icon: getCssVarColor('palette-neutral-500') }, background: { body: getCssVarColor('palette-common-white'), surface: getCssVarColor('palette-neutral-50'), popup: getCssVarColor('palette-common-white'), level1: getCssVarColor('palette-neutral-100'), level2: getCssVarColor('palette-neutral-200'), level3: getCssVarColor('palette-neutral-300'), tooltip: getCssVarColor('palette-neutral-500'), backdrop: `rgba(${getCssVar('palette-neutral-darkChannel', colorChannel(defaultColors.neutral[900]) // should be the same index as in `attachColorChannels` )} / 0.25)` }, divider: `rgba(${getCssVar('palette-neutral-mainChannel', colorChannel(defaultColors.neutral[500]) // should be the same index as in `attachColorChannels` )} / 0.2)`, focusVisible: getCssVarColor('palette-primary-500') }, shadowRing: '0 0 #000', shadowChannel: '21 21 21', shadowOpacity: '0.08' }; const darkColorSystem = { palette: { mode: 'dark', primary: _extends({}, defaultColors.primary, createDarkModeVariantVariables('primary')), neutral: _extends({}, defaultColors.neutral, createDarkModeVariantVariables('neutral'), { plainColor: getCssVarColor('palette-neutral-300'), plainHoverColor: getCssVarColor(`palette-neutral-300`) }), danger: _extends({}, defaultColors.danger, createDarkModeVariantVariables('danger')), success: _extends({}, defaultColors.success, createDarkModeVariantVariables('success')), warning: _extends({}, defaultColors.warning, createDarkModeVariantVariables('warning')), common: { white: '#FFF', black: '#000' }, text: { primary: getCssVarColor('palette-neutral-100'), secondary: getCssVarColor('palette-neutral-300'), tertiary: getCssVarColor('palette-neutral-400'), icon: getCssVarColor('palette-neutral-400') }, background: { body: getCssVarColor('palette-common-black'), surface: getCssVarColor('palette-neutral-900'), popup: getCssVarColor('palette-common-black'), level1: getCssVarColor('palette-neutral-800'), level2: getCssVarColor('palette-neutral-700'), level3: getCssVarColor('palette-neutral-600'), tooltip: getCssVarColor('palette-neutral-600'), backdrop: `rgba(${getCssVar('palette-neutral-darkChannel', colorChannel(defaultColors.neutral[50]) // should be the same index as in `attachColorChannels` )} / 0.25)` }, divider: `rgba(${getCssVar('palette-neutral-mainChannel', colorChannel(defaultColors.neutral[500]) // should be the same index as in `attachColorChannels` )} / 0.16)`, focusVisible: getCssVarColor('palette-primary-500') }, shadowRing: '0 0 #000', shadowChannel: '0 0 0', shadowOpacity: '0.6' }; const fontFamilyFallback = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"'; const fontFamily = _extends({ body: `"Inter", ${getCssVar(`fontFamily-fallback, ${fontFamilyFallback}`)}`, display: `"Inter", ${getCssVar(`fontFamily-fallback, ${fontFamilyFallback}`)}`, code: 'Source Code Pro,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace', fallback: fontFamilyFallback }, scalesInput.fontFamily); const fontWeight = _extends({ sm: 300, // regular md: 500, // medium lg: 600, // semi-bold xl: 700 }, scalesInput.fontWeight); const fontSize = _extends({ xs: '0.75rem', // 12px sm: '0.875rem', // 14px md: '1rem', // 16px lg: '1.125rem', // 18px xl: '1.25rem', // 20px xl2: '1.5rem', // 24px xl3: '1.875rem', // 30px xl4: '2.25rem' }, scalesInput.fontSize); const lineHeight = _extends({ xs: '1.33334', // largest font sizes: h1, h2 sm: '1.42858', // normal font sizes md: '1.5', // normal font sizes lg: '1.55556', // large font sizes for components xl: '1.66667' }, scalesInput.lineHeight); const defaultShadowRing = (_scalesInput$colorSch = (_scalesInput$colorSch2 = scalesInput.colorSchemes) == null || (_scalesInput$colorSch2 = _scalesInput$colorSch2.light) == null ? void 0 : _scalesInput$colorSch2.shadowRing) != null ? _scalesInput$colorSch : lightColorSystem.shadowRing; const defaultShadowChannel = (_scalesInput$colorSch3 = (_scalesInput$colorSch4 = scalesInput.colorSchemes) == null || (_scalesInput$colorSch4 = _scalesInput$colorSch4.light) == null ? void 0 : _scalesInput$colorSch4.shadowChannel) != null ? _scalesInput$colorSch3 : lightColorSystem.shadowChannel; const defaultShadowOpacity = (_scalesInput$colorSch5 = (_scalesInput$colorSch6 = scalesInput.colorSchemes) == null || (_scalesInput$colorSch6 = _scalesInput$colorSch6.light) == null ? void 0 : _scalesInput$colorSch6.shadowOpacity) != null ? _scalesInput$colorSch5 : lightColorSystem.shadowOpacity; const defaultScales = { colorSchemes: { light: lightColorSystem, dark: darkColorSystem }, fontSize, fontFamily, fontWeight, focus: { thickness: '2px', selector: `&.${generateUtilityClass('', 'focusVisible')}, &:focus-visible`, default: { outlineOffset: `var(--focus-outline-offset, ${getCssVar('focus-thickness', (_scalesInput$focus$th = (_scalesInput$focus = scalesInput.focus) == null ? void 0 : _scalesInput$focus.thickness) != null ? _scalesInput$focus$th : '2px')})`, outline: `${getCssVar('focus-thickness', (_scalesInput$focus$th2 = (_scalesInput$focus2 = scalesInput.focus) == null ? void 0 : _scalesInput$focus2.thickness) != null ? _scalesInput$focus$th2 : '2px')} solid ${getCssVar('palette-focusVisible', defaultColors.primary[500])}` } }, lineHeight, radius: { xs: '2px', sm: '6px', md: '8px', lg: '12px', xl: '16px' }, shadow: { xs: `${getCssVar('shadowRing', defaultShadowRing)}, 0px 1px 2px 0px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)})`, sm: `${getCssVar('shadowRing', defaultShadowRing)}, 0px 1px 2px 0px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)}), 0px 2px 4px 0px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)})`, md: `${getCssVar('shadowRing', defaultShadowRing)}, 0px 2px 8px -2px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)}), 0px 6px 12px -2px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)})`, lg: `${getCssVar('shadowRing', defaultShadowRing)}, 0px 2px 8px -2px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)}), 0px 12px 16px -4px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)})`, xl: `${getCssVar('shadowRing', defaultShadowRing)}, 0px 2px 8px -2px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)}), 0px 20px 24px -4px rgba(${getCssVar('shadowChannel', defaultShadowChannel)} / ${getCssVar('shadowOpacity', defaultShadowOpacity)})` }, zIndex: { badge: 1, table: 10, popup: 1000, modal: 1300, snackbar: 1400, tooltip: 1500 }, typography: { h1: { fontFamily: getCssVar(`fontFamily-display, ${fontFamily.display}`), fontWeight: getCssVar(`fontWeight-xl, ${fontWeight.xl}`), fontSize: getCssVar(`fontSize-xl4, ${fontSize.xl4}`), lineHeight: getCssVar(`lineHeight-xs, ${lineHeight.xs}`), letterSpacing: '-0.025em', color: getCssVar(`palette-text-primary, ${lightColorSystem.palette.text.primary}`) }, h2: { fontFamily: getCssVar(`fontFamily-display, ${fontFamily.display}`), fontWeight: getCssVar(`fontWeight-xl, ${fontWeight.xl}`), fontSize: getCssVar(`fontSize-xl3, ${fontSize.xl3}`), lineHeight: getCssVar(`lineHeight-xs, ${lineHeight.xs}`), letterSpacing: '-0.025em', color: getCssVar(`palette-text-primary, ${lightColorSystem.palette.text.primary}`) }, h3: { fontFamily: getCssVar(`fontFamily-display, ${fontFamily.display}`), fontWeight: getCssVar(`fontWeight-lg, ${fontWeight.lg}`), fontSize: getCssVar(`fontSize-xl2, ${fontSize.xl2}`), lineHeight: getCssVar(`lineHeight-xs, ${lineHeight.xs}`), letterSpacing: '-0.025em', color: getCssVar(`palette-text-primary, ${lightColorSystem.palette.text.primary}`) }, h4: { fontFamily: getCssVar(`fontFamily-display, ${fontFamily.display}`), fontWeight: getCssVar(`fontWeight-lg, ${fontWeight.lg}`), fontSize: getCssVar(`fontSize-xl, ${fontSize.xl}`), lineHeight: getCssVar(`lineHeight-md, ${lineHeight.md}`), letterSpacing: '-0.025em', color: getCssVar(`palette-text-primary, ${lightColorSystem.palette.text.primary}`) }, 'title-lg': { fontFamily: getCssVar(`fontFamily-body, ${fontFamily.body}`), fontWeight: getCssVar(`fontWeight-lg, ${fontWeight.lg}`), fontSize: getCssVar(`fontSize-lg, ${fontSize.lg}`), lineHeight: getCssVar(`lineHeight-xs, ${lineHeight.xs}`), color: getCssVar(`palette-text-primary, ${lightColorSystem.palette.text.primary}`) }, 'title-md': { fontFamily: getCssVar(`fontFamily-body, ${fontFamily.body}`), fontWeight: getCssVar(`fontWeight-md, ${fontWeight.md}`), fontSize: getCssVar(`fontSize-md, ${fontSize.md}`), lineHeight: getCssVar(`lineHeight-md, ${lineHeight.md}`), color: getCssVar(`palette-text-primary, ${lightColorSystem.palette.text.primary}`) }, 'title-sm': { fontFamily: getCssVar(`fontFamily-body, ${fontFamily.body}`), fontWeight: getCssVar(`fontWeight-md, ${fontWeight.md}`), fontSize: getCssVar(`fontSize-sm, ${fontSize.sm}`), lineHeight: getCssVar(`lineHeight-sm, ${lineHeight.sm}`), color: getCssVar(`palette-text-primary, ${lightColorSystem.palette.text.primary}`) }, 'body-lg': { fontFamily: getCssVar(`fontFamily-body, ${fontFamily.body}`), fontSize: getCssVar(`fontSize-lg, ${fontSize.lg}`), lineHeight: getCssVar(`lineHeight-md, ${lineHeight.md}`), color: getCssVar(`palette-text-secondary, ${lightColorSystem.palette.text.secondary}`) }, 'body-md': { fontFamily: getCssVar(`fontFamily-body, ${fontFamily.body}`), fontSize: getCssVar(`fontSize-md, ${fontSize.md}`), lineHeight: getCssVar(`lineHeight-md, ${lineHeight.md}`), color: getCssVar(`palette-text-secondary, ${lightColorSystem.palette.text.secondary}`) }, 'body-sm': { fontFamily: getCssVar(`fontFamily-body, ${fontFamily.body}`), fontSize: getCssVar(`fontSize-sm, ${fontSize.sm}`), lineHeight: getCssVar(`lineHeight-md, ${lineHeight.md}`), color: getCssVar(`palette-text-tertiary, ${lightColorSystem.palette.text.tertiary}`) }, 'body-xs': { fontFamily: getCssVar(`fontFamily-body, ${fontFamily.body}`), fontWeight: getCssVar(`fontWeight-md, ${fontWeight.md}`), fontSize: getCssVar(`fontSize-xs, ${fontSize.xs}`), lineHeight: getCssVar(`lineHeight-md, ${lineHeight.md}`), color: getCssVar(`palette-text-tertiary, ${lightColorSystem.palette.text.tertiary}`) } } }; const _ref2 = scalesInput ? deepmerge(defaultScales, scalesInput) : defaultScales, { colorSchemes } = _ref2, mergedScales = _objectWithoutPropertiesLoose(_ref2, _excluded2); const theme = _extends({ colorSchemes }, mergedScales, { breakpoints: createBreakpoints(breakpoints != null ? breakpoints : {}), components: deepmerge({ // TODO: find a way to abstract SvgIcon out of @mui/material MuiSvgIcon: { defaultProps: { fontSize: 'xl2' }, styleOverrides: { root: ({ ownerState, theme: themeProp }) => { var _themeProp$vars$palet; const instanceFontSize = ownerState.instanceFontSize; return _extends({ margin: 'var(--Icon-margin)' }, ownerState.fontSize && ownerState.fontSize !== 'inherit' && { fontSize: `var(--Icon-fontSize, ${themeProp.vars.fontSize[ownerState.fontSize]})` }, !ownerState.htmlColor && _extends({ color: `var(--Icon-color, ${theme.vars.palette.text.icon})` }, ownerState.color && ownerState.color !== 'inherit' && themeProp.vars.palette[ownerState.color] && { color: `rgba(${(_themeProp$vars$palet = themeProp.vars.palette[ownerState.color]) == null ? void 0 : _themeProp$vars$palet.mainChannel} / 1)` }), instanceFontSize && instanceFontSize !== 'inherit' && { '--Icon-fontSize': themeProp.vars.fontSize[instanceFontSize] }); } } } }, componentsInput), cssVarPrefix, getCssVar, spacing: createSpacing(spacing) }); // Need type casting due to module augmentation inside the repo /** Color channels generation */ function attachColorChannels(supportedColorScheme, palette) { Object.keys(palette).forEach(key => { const channelMapping = { main: '500', light: '200', dark: '700' }; if (supportedColorScheme === 'dark') { // @ts-ignore internal channelMapping.main = 400; } if (!palette[key].mainChannel && palette[key][channelMapping.main]) { palette[key].mainChannel = colorChannel(palette[key][channelMapping.main]); } if (!palette[key].lightChannel && palette[key][channelMapping.light]) { palette[key].lightChannel = colorChannel(palette[key][channelMapping.light]); } if (!palette[key].darkChannel && palette[key][channelMapping.dark]) { palette[key].darkChannel = colorChannel(palette[key][channelMapping.dark]); } }); } // Set the channels Object.entries(theme.colorSchemes).forEach(([supportedColorScheme, colorSystem]) => { attachColorChannels(supportedColorScheme, colorSystem.palette); }); // =============================================================== // Create `theme.vars` that contain `var(--*)` as values // =============================================================== const parserConfig = { prefix: cssVarPrefix, shouldSkipGeneratingVar }; const { vars: themeVars, generateCssVars } = prepareCssVars( // @ts-ignore property truDark is missing from colorSchemes _extends({ colorSchemes }, mergedScales), parserConfig); theme.vars = themeVars; theme.generateCssVars = generateCssVars; theme.unstable_sxConfig = _extends({}, defaultSxConfig, themeOptions == null ? void 0 : themeOptions.unstable_sxConfig); theme.unstable_sx = function sx(props) { return styleFunctionSx({ sx: props, theme: this }); }; theme.getColorSchemeSelector = colorScheme => colorScheme === 'light' ? '&' : `&[data-joy-color-scheme="${colorScheme}"], [data-joy-color-scheme="${colorScheme}"] &`; const createVariantInput = { getCssVar, palette: theme.colorSchemes.light.palette }; theme.variants = deepmerge({ plain: createVariant('plain', createVariantInput), plainHover: createVariant('plainHover', createVariantInput), plainActive: createVariant('plainActive', createVariantInput), plainDisabled: createVariant('plainDisabled', createVariantInput), outlined: createVariant('outlined', createVariantInput), outlinedHover: createVariant('outlinedHover', createVariantInput), outlinedActive: createVariant('outlinedActive', createVariantInput), outlinedDisabled: createVariant('outlinedDisabled', createVariantInput), soft: createVariant('soft', createVariantInput), softHover: createVariant('softHover', createVariantInput), softActive: createVariant('softActive', createVariantInput), softDisabled: createVariant('softDisabled', createVariantInput), solid: createVariant('solid', createVariantInput), solidHover: createVariant('solidHover', createVariantInput), solidActive: createVariant('solidActive', createVariantInput), solidDisabled: createVariant('solidDisabled', createVariantInput) }, variantsInput); theme.palette = _extends({}, theme.colorSchemes.light.palette, { colorScheme: 'light' }); theme.shouldSkipGeneratingVar = shouldSkipGeneratingVar; theme.applyStyles = applyStyles; return theme; }