All files / packages/design-tokens/src/style-dictionary/transforms/css light-dark-css.ts

93.33% Statements 14/15
83.33% Branches 5/6
100% Functions 4/4
93.33% Lines 14/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72                                  1x 8x               1x         11x     22x     4x       4x 4x       18x     11x 11x         11x             1x 2x                
import type {
  Config,
  Filter,
  PlatformConfig,
  TransformedToken,
  ValueTransform,
} from 'style-dictionary/types';
 
import type { StyleDictionaryHost } from '../../style-dictionary-host.js';
import { MODE_EXTENSION_KEY } from '../../utils/constants.js';
 
/**
 * CSS filter to detect tokens with light/dark values
 *
 * @param {Object} token
 * @returns boolean
 */
export const lightDarkFilter = ((token: TransformedToken, _options: Config) =>
  !!token.$extensions?.[MODE_EXTENSION_KEY]?.dark?.$value) satisfies Filter['filter'];
 
/**
 * CSS Transformer that converts light/dark mode values to light-dark() CSS function
 *
 * @param {Object} token
 * @returns
 */
export const lightDarkTransformer = ((
  token: TransformedToken,
  _platform: PlatformConfig,
  _options: Config,
) => {
  const resolveReference = (value, originalValue) => {
    // If the value is dynamic, check if it's an alias reference
    // Aliases are resolved by Style Dictionary and should use the resolved value
    if (token.dynamic) {
      // If original value is an alias reference, use the resolved value instead
      // Aliases don't generate CSS variables, so we need to use the literal resolved value
      Iif (originalValue && originalValue.includes('{alias.')) {
        return value; // Use the resolved value (e.g., #fff) instead of creating a CSS variable
      }
      // Otherwise, convert token name to CSS variable reference syntax
      const tokenName = originalValue.replace('{', '').replace('}', '').replace(/\./g, '-');
      return `var(--${tokenName})`;
    }
 
    // Otherwise return the literal value
    return value;
  };
 
  const lightVal = resolveReference(token.$value, token.original.$value);
  const darkVal = resolveReference(
    token.$extensions[MODE_EXTENSION_KEY].dark.$value,
    token.original.$extensions[MODE_EXTENSION_KEY].dark.$value,
  );
 
  return `light-dark(${lightVal}, ${darkVal})`;
}) satisfies ValueTransform['transform'];
 
/**
 * Style Dictionary registration for the light-dark CSS transform
 * @param {StyleDictionary} StyleDictionary
 */
export const lightDarkCSS = (StyleDictionary: StyleDictionaryHost) => {
  StyleDictionary.registerTransform({
    name: 'value/light-dark-css-var',
    type: 'value',
    transitive: true,
    filter: lightDarkFilter,
    transform: lightDarkTransformer,
  } satisfies ValueTransform);
};