element-book
Version:
An [`element-vir`](https://npmjs.com/package/element-vir) drop-in element for building, testing, and demonstrating a collection of elements (or, in other words, a design system).
94 lines (93 loc) • 3.16 kB
JavaScript
import { mapObjectValues } from '@augment-vir/common';
import Color from 'colorjs.io';
import { unsafeCSS } from 'element-vir';
function colorsObjectToCssResult(colors) {
return mapObjectValues(colors, (key, value) => {
if (value instanceof Color) {
return unsafeCSS(value.toString({ format: 'hex' }));
}
else {
return colorsObjectToCssResult(value);
}
});
}
/**
* The default theme color.
*
* @category Internal
*/
export const defaultThemeStartColor = 'dodgerblue';
function calculateTextColorString(color) {
const onWhite = Math.abs(color.contrast('white', 'APCA'));
const onBlack = Math.abs(color.contrast('black', 'APCA'));
const textColorString = onWhite > onBlack ? 'white' : 'black';
return textColorString;
}
function createColorPair({ background, foreground, }) {
return {
background: background ?? new Color(calculateTextColorString(foreground)),
foreground: foreground ?? new Color(calculateTextColorString(background)),
};
}
/**
* Theme style options for the element-book app.
*
* @category Internal
*/
export var ThemeStyle;
(function (ThemeStyle) {
ThemeStyle["Dark"] = "dark";
ThemeStyle["Light"] = "light";
})(ThemeStyle || (ThemeStyle = {}));
function flipBackForeground(input) {
return input === 'black' ? 'white' : 'black';
}
const faintForegroundColors = {
black: {
foregroundFaint1: new Color('#ccc'),
foregroundFaint2: new Color('#eee'),
},
white: {
foregroundFaint1: new Color('#ccc'),
foregroundFaint2: new Color('#eee'),
},
};
const faintBackgroundColors = {
black: {
backgroundFaint1: new Color('#666'),
backgroundFaint2: new Color('#444'),
},
white: {
backgroundFaint1: new Color('#ccc'),
backgroundFaint2: new Color('#fafafa'),
},
};
/**
* Creates a theme from the given theme configuration.
*
* @category Internal
*/
export function createTheme({ themeColor: inputThemeColor = defaultThemeStartColor, themeStyle = ThemeStyle.Light, } = {}) {
const themeColor = new Color(inputThemeColor);
const backgroundColor = new Color(themeStyle === ThemeStyle.Dark ? 'black' : 'white');
const foregroundColorString = calculateTextColorString(backgroundColor);
const foregroundColor = new Color(foregroundColorString);
const colors = {
nav: {
hover: createColorPair({ background: themeColor.clone().set({ 'hsl.l': 93 }) }),
active: createColorPair({ background: themeColor.clone().set({ 'hsl.l': 90 }) }),
selected: createColorPair({ background: themeColor.clone().set({ 'hsl.l': 85 }) }),
},
accent: {
icon: themeColor.clone().set({ 'hsl.l': 40 }),
},
page: {
background: backgroundColor,
...faintBackgroundColors[flipBackForeground(foregroundColorString)],
foreground: foregroundColor,
...faintForegroundColors[foregroundColorString],
},
};
const convertedToCssResults = colorsObjectToCssResult(colors);
return convertedToCssResults;
}