72 lines
2.0 KiB
TypeScript

import { rgba, lighten, darken } from 'polished';
import { window } from 'global';
import { logger } from '@storybook/client-logger';
export const mkColor = (color: string) => ({ color });
// Check if it is a string. This is for the sake of warning users
// and the successive guarding logics that use String methods.
const isColorString = (color: string) => {
if (typeof color !== 'string') {
logger.warn(
`Color passed to theme object should be a string. Instead ` +
`${color}(${typeof color}) was passed.`
);
return false;
}
return true;
};
// Passing arguments that can't be converted to RGB such as linear-gradient
// to library polished's functions such as lighten or darken throws the error
// that crashes the entire storybook. It needs to be guarded when arguments
// of those functions are from user input.
const isValidColorForPolished = (color: string) => {
return !/(gradient|var|calc)/.test(color);
};
const applyPolished = (type: string, color: string) => {
if (type === 'darken') {
return rgba(`${darken(1, color)}`, 0.95);
}
if (type === 'lighten') {
return rgba(`${lighten(1, color)}`, 0.95);
}
return color;
};
const colorFactory = (type: string) => (color: string) => {
if (!isColorString(color)) {
return color;
}
if (!isValidColorForPolished(color)) {
return color;
}
// Guard anything that is not working with polished.
try {
return applyPolished(type, color);
} catch (error) {
return color;
}
};
export const lightenColor = colorFactory('lighten');
export const darkenColor = colorFactory('darken');
// The default color scheme is light so unless the preferred color
// scheme is set to dark we always want to use the light theme
export const getPreferredColorScheme = () => {
if (!window || !window.matchMedia) return 'light';
const isDarkThemePreferred = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (isDarkThemePreferred) return 'dark';
return 'light';
};