theme-vir
Version:
Create an entire web theme.
108 lines (107 loc) • 3.77 kB
JavaScript
import { getObjectTypedEntries, getObjectTypedKeys, getObjectTypedValues, mapObjectValues, } from '@augment-vir/common';
import { setCssVarValue } from 'lit-css-vars';
import { createColorCssVarDefault, defineColorTheme, themeDefaultKey, } from './color-theme.js';
function applyCssVarOverride({ originalTheme, layerKey, themeColor, override, overrideValues, }) {
const layerOverride = override?.[layerKey];
if (!layerOverride) {
return;
}
overrideValues[String(themeColor[layerKey].name)] = String(createColorCssVarDefault(layerKey, layerOverride, originalTheme.init.default, originalTheme.init.colors));
}
/**
* Define a color theme override. Use this to define multiple theme variations, like light mode vs
* dark mode.
*
* @category Color Theme
*/
export function defineColorThemeOverride(originalTheme, overrideName, { defaultOverride, colorOverrides, }) {
const defaultValues = {};
if (defaultOverride) {
getObjectTypedKeys(defaultOverride).forEach((layerKey) => {
applyCssVarOverride({
originalTheme,
layerKey,
override: defaultOverride,
themeColor: originalTheme.colors[themeDefaultKey],
overrideValues: defaultValues,
});
});
}
const colorValues = {};
if (colorOverrides) {
getObjectTypedEntries(colorOverrides).forEach(([colorName, override,]) => {
const themeColor = originalTheme.colors[colorName];
if (!themeColor) {
throw new Error(`Override color name '${String(colorName)}' does not exist in the theme being overridden.`);
}
applyCssVarOverride({
originalTheme,
layerKey: 'foreground',
override,
themeColor,
overrideValues: colorValues,
});
applyCssVarOverride({
originalTheme,
layerKey: 'background',
override,
themeColor,
overrideValues: colorValues,
});
});
}
const asThemeColorInit = mapObjectValues(originalTheme.init.colors, (colorName, colorInit) => {
const override = colorOverrides?.[colorName];
const newInit = {
...colorInit,
...override,
};
return newInit;
});
const asTheme = defineColorTheme({
...originalTheme.init.default,
...defaultOverride,
}, asThemeColorInit);
return {
name: overrideName,
overrides: {
...defaultValues,
...colorValues,
},
originalTheme,
asTheme,
};
}
/**
* Set all color theme CSS vars on the given element. If no override is given, the theme color
* default values are assigned.
*
* @category Color Theme
*/
export function applyColorTheme(
/** This should usually be the top-level `html` element. */
element, fullTheme, themeOverride) {
getObjectTypedValues(fullTheme.colors).forEach((themeColor) => {
applyIndividualThemeColorValue({
element,
layerKey: 'background',
themeColor,
themeOverride,
});
applyIndividualThemeColorValue({
element,
layerKey: 'foreground',
themeColor,
themeOverride,
});
});
}
function applyIndividualThemeColorValue({ element, layerKey, themeOverride, themeColor, }) {
const override = themeOverride?.overrides[String(themeColor[layerKey].name)];
const value = override || themeColor[layerKey].default;
setCssVarValue({
forCssVar: themeColor[layerKey],
onElement: element,
toValue: value,
});
}