All files / packages/theme-selector/src theme-mapper.ts

100% Statements 11/11
100% Branches 8/8
100% Functions 5/5
100% Lines 11/11

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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104                                                                                      536x             536x   536x 2x     534x 112x     422x             536x             536x                               536x 536x                        
// SPDX-License-Identifier: MIT
/**
 * Maps core theme flavors to UI-specific format
 */
 
import type { ThemeFlavor as CanonicalThemeFlavor } from '@lgtm-hq/turbo-themes-core';
import type { ThemeFamily } from './types.js';
import {
  DEFAULT_FAMILY,
  VENDOR_FAMILY_MAP,
  VENDOR_ICON_MAP,
  FLAVOR_DESCRIPTIONS,
  type AppearanceIcons,
} from './generated/theme-maps.js';
 
export type { AppearanceIcons };
export { VENDOR_ICON_MAP };
 
export interface ThemeColors {
  bg: string;
  surface: string;
  accent: string;
  text: string;
}
 
export interface ThemeFlavor extends Pick<CanonicalThemeFlavor, 'id' | 'appearance' | 'vendor'> {
  id: string;
  name: string;
  description: string;
  cssFile: string;
  icon?: string | undefined;
  family: ThemeFamily;
  colors: ThemeColors;
}
 
// ============================================================================
// Helper Functions
// ============================================================================
 
/**
 * Gets the theme family from vendor name
 */
function getFamily(vendor: string): ThemeFamily {
  return VENDOR_FAMILY_MAP[vendor] ?? DEFAULT_FAMILY;
}
 
/**
 * Gets icon path for a vendor
 */
function getIconForVendor(vendor: string, appearance: 'light' | 'dark'): string | undefined {
  const iconConfig = VENDOR_ICON_MAP[vendor];
 
  if (!iconConfig) {
    return undefined;
  }
 
  if (typeof iconConfig === 'string') {
    return iconConfig;
  }
 
  return iconConfig[appearance];
}
 
/**
 * Gets description for a flavor
 */
function getDescriptionForFlavor(id: string, label: string): string {
  return FLAVOR_DESCRIPTIONS[id] ?? `${label} theme`;
}
 
/**
 * Extracts preview colors from theme tokens
 */
function extractPreviewColors(tokens: CanonicalThemeFlavor['tokens']): ThemeColors {
  return {
    bg: tokens.background.base,
    surface: tokens.background.surface,
    accent: tokens.brand.primary,
    text: tokens.text.primary,
  };
}
 
// ============================================================================
// Public API
// ============================================================================
 
/**
 * Maps a canonical theme flavor to UI-specific format
 */
export function mapFlavorToUI(flavor: CanonicalThemeFlavor): ThemeFlavor {
  const family = getFamily(flavor.vendor);
  return {
    id: flavor.id,
    name: flavor.label,
    description: getDescriptionForFlavor(flavor.id, flavor.label),
    cssFile: `assets/css/themes/turbo/${flavor.id}.css`,
    icon: getIconForVendor(flavor.vendor, flavor.appearance),
    family,
    vendor: flavor.vendor,
    appearance: flavor.appearance,
    colors: extractPreviewColors(flavor.tokens),
  };
}