UNPKG

theme-vir

Version:
160 lines (159 loc) 6.46 kB
import { assert, check } from '@augment-vir/assert'; import { getObjectTypedEntries, log } from '@augment-vir/common'; import { defineCssVars, } from 'lit-css-vars'; /** * Handles a color init value. * * @category Internal */ export function createColorCssVarDefault(fromName, init, defaultInit, colorsInit) { const referenceKey = check.hasKey(init, 'refBackground') ? 'refBackground' : check.hasKey(init, 'refForeground') ? 'refForeground' : undefined; const reference = referenceKey && check.hasKey(init, referenceKey) ? init[referenceKey] : undefined; if (reference) { const layerKey = referenceKey === 'refBackground' ? 'background' : 'foreground'; const referenced = colorsInit[reference]; if (!referenced) { throw new Error(`Color theme ${referenceKey} reference '${reference}' does not exist. (Referenced from '${fromName}'.)`); } const colorValue = referenced[layerKey] || (layerKey === 'foreground' ? createColorCssVarDefault('default-fg', defaultInit.foreground, defaultInit, colorsInit) : createColorCssVarDefault('default-bg', defaultInit.background, defaultInit, colorsInit)); return `var(--${reference}-${layerKey === 'foreground' ? 'fg' : 'bg'}, ${createColorCssVarDefault(reference, colorValue, defaultInit, colorsInit)})`; } else { return init; } } /** * Default foreground/background color theme used in {@link ColorTheme}. Do not define a theme color * with this name! * * @category Internal */ export const themeDefaultKey = 'theme-default'; /** * Define a color theme. * * @category Color Theme */ export function defineColorTheme(defaultInit, allColorsInit) { try { if (themeDefaultKey in allColorsInit) { throw new Error(`Cannot define theme color by name '${themeDefaultKey}', it is used internally.`); } const defaultColors = defineCssVars({ 'default-fg': createColorCssVarDefault('default-fg', defaultInit.foreground, defaultInit, allColorsInit), 'default-bg': createColorCssVarDefault('default-bg', defaultInit.background, defaultInit, allColorsInit), 'default-inverse-fg': createColorCssVarDefault('default-inverse-fg', defaultInit.background, defaultInit, allColorsInit), 'default-inverse-bg': createColorCssVarDefault('default-inverse-bg', defaultInit.foreground, defaultInit, allColorsInit), }); const cssVarsSetup = getObjectTypedEntries(allColorsInit).reduce((accum, [colorName, colorInit,]) => { const names = createCssVarNames(colorName); accum[names.foreground] = colorInit.foreground ? createColorCssVarDefault([ colorName, 'foreground', ].join(' '), colorInit.foreground, defaultInit, allColorsInit) : `var(${defaultColors['default-fg'].name}, ${defaultColors['default-fg'].default})`; accum[names.background] = colorInit.background ? createColorCssVarDefault([ colorName, 'background', ].join(' '), colorInit.background, defaultInit, allColorsInit) : `var(${defaultColors['default-bg'].name}, ${defaultColors['default-bg'].default})`; accum[names.foregroundInverse] = `var(--${names.background}, ${accum[names.background]})`; accum[names.backgroundInverse] = `var(--${names.foreground}, ${accum[names.foreground]})`; return accum; }, {}); /** * This has multiple `as` casts because `defineCssVars` complains that `cssVarsSetup` is too * generic. That is indeed true, but in this use case we do not care because the resulting * `cssVars` object is not directly exposed. */ const cssVars = defineCssVars(cssVarsSetup); const colors = {}; const inverseColors = {}; getObjectTypedEntries(allColorsInit).forEach(([colorName, colorInit,]) => { assert.isString(colorName); const names = createCssVarNames(colorName); const foreground = cssVars[names.foreground]; const background = cssVars[names.background]; const foregroundInverse = cssVars[names.foregroundInverse]; const backgroundInverse = cssVars[names.backgroundInverse]; assert.isDefined(foreground); assert.isDefined(background); assert.isDefined(foregroundInverse); assert.isDefined(backgroundInverse); colors[colorName] = { foreground, background, init: colorInit, name: colorName, }; inverseColors[colorName] = { foreground: foregroundInverse, background: backgroundInverse, init: colorInit, name: colorName, }; }); const themeDefaultColors = { foreground: defaultColors['default-fg'], background: defaultColors['default-bg'], init: defaultInit, name: themeDefaultKey, }; const themeDefaultInverseColors = { ...themeDefaultColors, foreground: defaultColors['default-inverse-fg'], background: defaultColors['default-inverse-bg'], }; return { colors: { [themeDefaultKey]: themeDefaultColors, ...colors, }, inverse: { [themeDefaultKey]: themeDefaultInverseColors, ...inverseColors, }, init: { colors: allColorsInit, default: defaultInit, }, }; } catch (error) { globalThis.setTimeout(() => log.error(error)); throw error; } } function createCssVarNames(colorName) { return { foreground: [ colorName, 'fg', ].join('-'), background: [ colorName, 'bg', ].join('-'), foregroundInverse: [ colorName, 'inverse', 'fg', ].join('-'), backgroundInverse: [ colorName, 'inverse', 'bg', ].join('-'), }; }