@workday/canvas-kit-react
Version:
The parent module that contains all Workday Canvas Kit React components
76 lines (75 loc) • 3.28 kB
JavaScript
import chroma from 'chroma-js';
import colors from '@workday/canvas-colors-web';
import { defaultCanvasTheme } from './theme';
import { ContentDirection, } from './types';
import { pickForegroundColor } from '../utils';
// Should these be exported?
import { deepMerge } from '../utils/deepMerge';
import { memoize } from '../utils/memoize';
export const shiftColor = memoize((hexColor, amount = 100) => {
const canvasColor = Object.keys(colors).find(color => colors[color] === hexColor);
if (canvasColor) {
const colorRegex = /([a-zAz]*)(\d{3})/g;
const match = colorRegex.exec(canvasColor);
if (match) {
const baseColor = match[1];
const shadeNumber = parseInt(match[2], 10);
const newShade = shadeNumber + amount;
if (newShade >= 100 && newShade <= 600) {
return colors[(baseColor + newShade)];
}
}
}
try {
const newColor = amount > 0
? chroma(hexColor).darken(amount / 100)
: chroma(hexColor).brighten(-amount / 100);
return newColor.hex();
}
catch (e) {
console.warn(`Invalid color '${hexColor}' used in theme`);
return hexColor;
}
}, (color, value) => `${color}.${value}`);
function fillPalette(defaultPalette, palette) {
if (!palette) {
return {};
}
const main = palette.main || defaultPalette.main;
const dark = palette.dark || (palette.main && shiftColor(palette.main, 100)) || defaultPalette.dark;
const darkest = palette.darkest || (palette.main && shiftColor(palette.main, 200)) || defaultPalette.darkest;
const light = palette.light || (palette.main && shiftColor(palette.main, -100)) || defaultPalette.light;
const lightest = palette.lightest || (palette.main && shiftColor(palette.main, -200)) || defaultPalette.lightest;
const contrast = palette.contrast || pickForegroundColor(main) || defaultPalette.contrast;
return {
lightest,
light,
main,
dark,
darkest,
contrast,
};
}
function calculateCanvasTheme(partialTheme) {
const { palette = {}, breakpoints = {}, direction, ...extraFields } = partialTheme;
const { primary, alert, error, success, neutral, common = {} } = palette;
const mergeable = {
palette: {
common,
primary: fillPalette(defaultCanvasTheme.palette.primary, primary),
alert: fillPalette(defaultCanvasTheme.palette.alert, alert),
error: fillPalette(defaultCanvasTheme.palette.error, error),
success: fillPalette(defaultCanvasTheme.palette.success, success),
neutral: fillPalette(defaultCanvasTheme.palette.neutral, neutral),
},
breakpoints,
direction: direction === ContentDirection.RTL ? direction : ContentDirection.LTR,
};
return deepMerge(deepMerge({}, defaultCanvasTheme), { ...mergeable, ...extraFields });
}
/**
* Creates a full {@link CanvasTheme} from any partial theme by deeply merging with the
* `defaultCanvasTheme` object. The function is memoized, but it is best to run this function
* only once and save the result.
*/
export const createCanvasTheme = memoize(calculateCanvasTheme, (...args) => JSON.stringify(args));